GCC Code Coverage Report


Directory: ./
File: sql/item_func.cc
Date: 2022-12-06 21:40:42
Exec Total Coverage
Lines: 4973 5351 92.9%
Branches: 4142 6279 66.0%

Line Branch Exec Source
1 /* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @file
25
26 @brief
27 This file defines all numerical Items
28 */
29
30 #include "sql/item_func.h"
31
32 #include <algorithm>
33 #include <atomic>
34 #include <cfloat> // DBL_DIG
35 #include <cmath> // std::log2
36 #include <cstdio>
37 #include <cstring>
38 #include <ctime>
39 #include <initializer_list>
40 #include <iosfwd>
41 #include <limits> // std::numeric_limits
42 #include <memory>
43 #include <new>
44 #include <string>
45 #include <type_traits>
46 #include <unordered_map>
47 #include <utility>
48
49 #include "integer_digits.h"
50 #include "m_string.h"
51 #include "map_helpers.h"
52 #include "mutex_lock.h" // MUTEX_LOCK
53 #include "my_bit.h" // my_count_bits
54 #include "my_bitmap.h"
55 #include "my_byteorder.h"
56 #include "my_dbug.h"
57 #include "my_double2ulonglong.h"
58 #include "my_hostname.h"
59 #include "my_loglevel.h"
60 #include "my_psi_config.h"
61 #include "my_sqlcommand.h"
62 #include "my_sys.h"
63 #include "my_systime.h"
64 #include "my_thread.h"
65 #include "my_user.h" // parse_user
66 #include "mysql/components/services/bits/mysql_cond_bits.h"
67 #include "mysql/components/services/bits/mysql_mutex_bits.h"
68 #include "mysql/components/services/bits/psi_bits.h"
69 #include "mysql/components/services/bits/psi_mutex_bits.h"
70 #include "mysql/components/services/log_builtins.h"
71 #include "mysql/components/services/log_shared.h"
72 #include "mysql/mysql_lex_string.h"
73 #include "mysql/plugin_audit.h"
74 #include "mysql/psi/mysql_cond.h"
75 #include "mysql/psi/mysql_mutex.h"
76 #include "mysql/service_mysql_password_policy.h"
77 #include "mysql/service_thd_wait.h"
78 #include "mysql/status_var.h"
79 #include "prealloced_array.h"
80 #include "sql-common/json_dom.h" // Json_wrapper
81 #include "sql/auth/auth_acls.h"
82 #include "sql/auth/auth_common.h" // check_password_strength
83 #include "sql/auth/sql_security_ctx.h"
84 #include "sql/binlog.h" // mysql_bin_log
85 #include "sql/check_stack.h"
86 #include "sql/current_thd.h" // current_thd
87 #include "sql/dd/info_schema/table_stats.h" // dd::info_schema::Table_stati...
88 #include "sql/dd/info_schema/tablespace_stats.h" // dd::info_schema::Tablesp...
89 #include "sql/dd/object_id.h"
90 #include "sql/dd/properties.h" // dd::Properties
91 #include "sql/dd/types/abstract_table.h"
92 #include "sql/dd/types/column.h"
93 #include "sql/dd/types/index.h" // Index::enum_index_type
94 #include "sql/dd_sql_view.h" // push_view_warning_or_error
95 #include "sql/dd_table_share.h" // dd_get_old_field_type
96 #include "sql/debug_sync.h" // DEBUG_SYNC
97 #include "sql/derror.h" // ER_THD
98 #include "sql/error_handler.h" // Internal_error_handler
99 #include "sql/item.h" // Item_json
100 #include "sql/item_cmpfunc.h" // get_datetime_value
101 #include "sql/item_json_func.h" // get_json_wrapper
102 #include "sql/item_strfunc.h" // Item_func_concat_ws
103 #include "sql/item_subselect.h" // Item_subselect
104 #include "sql/key.h"
105 #include "sql/log_event.h" // server_version
106 #include "sql/mdl.h"
107 #include "sql/mysqld.h" // log_10 stage_user_sleep
108 #include "sql/parse_tree_helpers.h" // PT_item_list
109 #include "sql/parse_tree_node_base.h" // Parse_context
110 #include "sql/protocol.h"
111 #include "sql/psi_memory_key.h"
112 #include "sql/resourcegroups/resource_group.h"
113 #include "sql/resourcegroups/resource_group_basic_types.h"
114 #include "sql/resourcegroups/resource_group_mgr.h"
115 #include "sql/rpl_gtid.h"
116 #include "sql/rpl_mi.h" // Master_info
117 #include "sql/rpl_msr.h" // channel_map
118 #include "sql/rpl_rli.h" // Relay_log_info
119 #include "sql/sp.h" // sp_setup_routine
120 #include "sql/sp_head.h" // sp_name
121 #include "sql/sp_pcontext.h" // sp_variable
122 #include "sql/sql_array.h" // just to keep clang happy
123 #include "sql/sql_audit.h" // audit_global_variable
124 #include "sql/sql_base.h" // Internal_error_handler_holder
125 #include "sql/sql_bitmap.h"
126 #include "sql/sql_class.h" // THD
127 #include "sql/sql_cmd.h"
128 #include "sql/sql_derived.h" // Condition_pushdown
129 #include "sql/sql_error.h"
130 #include "sql/sql_exchange.h" // sql_exchange
131 #include "sql/sql_executor.h"
132 #include "sql/sql_lex.h"
133 #include "sql/sql_list.h"
134 #include "sql/sql_load.h" // Sql_cmd_load_table
135 #include "sql/sql_optimizer.h" // JOIN
136 #include "sql/sql_parse.h" // check_stack_overrun
137 #include "sql/sql_show.h" // append_identifier
138 #include "sql/sql_time.h" // TIME_from_longlong_packed
139 #include "sql/sql_zip_dict.h"
140 #include "sql/strfunc.h" // find_type
141 #include "sql/system_variables.h"
142 #include "sql/thd_raii.h"
143 #include "sql/val_int_compare.h" // Integer_value
144 #include "sql_string.h"
145 #include "template_utils.h" // pointer_cast
146 #include "thr_mutex.h"
147
148 using std::max;
149 using std::min;
150
151 180506 static void free_user_var(user_var_entry *entry) { entry->destroy(); }
152
153 static int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
154 const Name_string &name,
155 user_var_entry **out_entry);
156
157 8233 bool check_reserved_words(const char *name) {
158 8233 if (!my_strcasecmp(system_charset_info, name, "GLOBAL") ||
159
6/6
✓ Branch 0 taken 8176 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 8134 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 111 times.
✓ Branch 5 taken 8122 times.
16367 !my_strcasecmp(system_charset_info, name, "LOCAL") ||
160
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 8122 times.
8134 !my_strcasecmp(system_charset_info, name, "SESSION"))
161 111 return true;
162 8122 return false;
163 }
164
165 57 void report_conversion_error(const CHARSET_INFO *to_cs, const char *from,
166 size_t from_length, const CHARSET_INFO *from_cs) {
167 char printable_buff[32];
168
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 convert_to_printable(printable_buff, sizeof(printable_buff), from,
169 from_length, from_cs, 6);
170 57 const char *from_name = from_cs->csname;
171 57 const char *to_name = to_cs->csname;
172
1/2
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
57 my_error(ER_CANNOT_CONVERT_STRING, MYF(0), printable_buff, from_name,
173 to_name);
174 57 }
175
176 /**
177 Simplify the string arguments to a function, if possible.
178
179 Currently used to substitute const values with character strings
180 in the desired character set. Only used during resolving.
181
182 @param thd thread handler
183 @param c Desired character set and collation
184 @param args Pointer to argument array
185 @param nargs Number of arguments to process
186
187 @returns false if success, true if error
188 */
189 977457 bool simplify_string_args(THD *thd, const DTCollation &c, Item **args,
190 uint nargs) {
191 // Only used during resolving
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 977457 times.
977457 assert(!thd->lex->is_exec_started());
193
194
2/2
✓ Branch 0 taken 117870 times.
✓ Branch 1 taken 859587 times.
977457 if (thd->lex->is_view_context_analysis()) return false;
195
196 uint i;
197 Item **arg;
198
2/2
✓ Branch 0 taken 859750 times.
✓ Branch 1 taken 859586 times.
1719336 for (i = 0, arg = args; i < nargs; i++, arg++) {
199 size_t dummy_offset;
200 // Only convert const values.
201
3/4
✓ Branch 0 taken 859750 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30491 times.
✓ Branch 3 taken 829259 times.
1677911 if (!(*arg)->const_item()) continue;
202
3/4
✓ Branch 0 taken 829259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 818160 times.
✓ Branch 3 taken 11099 times.
829259 if (!String::needs_conversion(1, (*arg)->collation.collation, c.collation,
203 &dummy_offset))
204 818160 continue;
205
206 11099 StringBuffer<STRING_BUFFER_USUAL_SIZE> original;
207 11099 StringBuffer<STRING_BUFFER_USUAL_SIZE> converted;
208
1/2
✓ Branch 0 taken 11099 times.
✗ Branch 1 not taken.
11099 String *ostr = (*arg)->val_str(&original);
209
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11098 times.
11099 if (ostr == nullptr) {
210
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (thd->is_error()) return true;
211
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 *arg = new (thd->mem_root) Item_null;
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*arg == nullptr) return true;
213 1 continue;
214 }
215 uint conv_status;
216
1/2
✓ Branch 0 taken 11098 times.
✗ Branch 1 not taken.
11098 converted.copy(ostr->ptr(), ostr->length(), ostr->charset(), c.collation,
217 &conv_status);
218
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11097 times.
11098 if (conv_status != 0) {
219
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 report_conversion_error(c.collation, ostr->ptr(), ostr->length(),
220 ostr->charset());
221 1 return true;
222 }
223 // If source is a binary string, the string may have to be validated:
224
3/6
✓ Branch 0 taken 11097 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11097 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11097 times.
11097 if (c.collation != &my_charset_bin && ostr->charset() == &my_charset_bin &&
225 !converted.is_valid_string(c.collation)) {
226 report_conversion_error(c.collation, ostr->ptr(), ostr->length(),
227 ostr->charset());
228 return true;
229 }
230
231
1/2
✓ Branch 0 taken 11097 times.
✗ Branch 1 not taken.
11097 char *ptr = thd->strmake(converted.ptr(), converted.length());
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11097 times.
11097 if (ptr == nullptr) return true;
233 Item *conv = new (thd->mem_root)
234
2/4
✓ Branch 0 taken 11097 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11097 times.
✗ Branch 3 not taken.
11097 Item_string(ptr, converted.length(), converted.charset(), c.derivation);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11097 times.
11097 if (conv == nullptr) return true;
236
237 11097 *arg = conv;
238
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11097 times.
11097 assert(conv->fixed);
240
6/6
✓ Branch 0 taken 11097 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 11097 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
11101 }
241 859586 return false;
242 }
243
244 /**
245 Evaluate an argument string and return it in the desired character set.
246 Perform character set conversion if needed.
247 Perform character set validation (from a binary string) if needed.
248
249 @param to_cs The desired character set
250 @param arg Argument to evaluate as a string value
251 @param buffer String buffer where argument is evaluated, if necessary
252
253 @returns string pointer if success, NULL if error or NULL value
254 */
255
256 692287405 String *eval_string_arg(const CHARSET_INFO *to_cs, Item *arg, String *buffer) {
257
1/2
✓ Branch 0 taken 692287718 times.
✗ Branch 1 not taken.
692287405 StringBuffer<STRING_BUFFER_USUAL_SIZE> local_string(nullptr, 0, to_cs);
258
259 size_t offset;
260 const bool convert =
261
1/2
✓ Branch 0 taken 692287659 times.
✗ Branch 1 not taken.
692287718 String::needs_conversion(0, arg->collation.collation, to_cs, &offset);
262
3/4
✓ Branch 0 taken 4917765 times.
✓ Branch 1 taken 687369894 times.
✓ Branch 2 taken 692287559 times.
✗ Branch 3 not taken.
692287659 String *res = arg->val_str(convert ? &local_string : buffer);
263
264 // Return immediately if argument is a NULL value, or there was an error
265
2/2
✓ Branch 0 taken 2973662 times.
✓ Branch 1 taken 689313897 times.
692287559 if (res == nullptr) {
266 2973662 return nullptr;
267 }
268
2/2
✓ Branch 0 taken 4917445 times.
✓ Branch 1 taken 684396452 times.
689313897 if (convert) {
269 /*
270 String must be converted from source character set. It has been built
271 in the "local_string" buffer and will be copied with conversion into the
272 caller provided buffer.
273 */
274 4917445 uint errors = 0;
275 4917445 buffer->length(0);
276
1/2
✓ Branch 0 taken 4917445 times.
✗ Branch 1 not taken.
4917444 buffer->copy(res->ptr(), res->length(), res->charset(), to_cs, &errors);
277
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4917440 times.
4917445 if (errors) {
278
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 report_conversion_error(to_cs, res->ptr(), res->length(), res->charset());
279 5 return nullptr;
280 }
281 4917440 return buffer;
282 }
283 // If source is a binary string, the string may have to be validated:
284
6/6
✓ Branch 0 taken 684140082 times.
✓ Branch 1 taken 256370 times.
✓ Branch 2 taken 741226 times.
✓ Branch 3 taken 683398856 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 684396422 times.
685137678 if (to_cs != &my_charset_bin && arg->collation.collation == &my_charset_bin &&
285
3/4
✓ Branch 0 taken 741226 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 741196 times.
741226 !res->is_valid_string(to_cs)) {
286
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 report_conversion_error(to_cs, res->ptr(), res->length(), res->charset());
287 30 return nullptr;
288 }
289 // Adjust target character set to the desired value
290 684396422 res->set_charset(to_cs);
291 684396390 return res;
292 692287527 }
293
294 /**
295 Evaluate a constant condition, represented by an Item tree
296
297 @param thd Thread handler
298 @param cond The constant condition to evaluate
299 @param[out] value Returned value, either true or false
300
301 @returns false if evaluation is successful, true otherwise
302 */
303
304 30477 bool eval_const_cond(THD *thd, Item *cond, bool *value) {
305 // Function may be used both during resolving and during optimization:
306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30477 times.
30477 assert(cond->may_evaluate_const(thd));
307 30477 *value = cond->val_bool();
308 30477 return thd->is_error();
309 }
310
311 /**
312 Test if the sum of arguments overflows the ulonglong range.
313 */
314 1667037 static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2) {
315 1667037 return ULLONG_MAX - arg1 < arg2;
316 }
317
318 5253495 bool Item_func::set_arguments(mem_root_deque<Item *> *list, bool context_free) {
319 5253495 allowed_arg_cols = 1;
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5253496 times.
5253495 if (alloc_args(*THR_MALLOC, list->size())) return true;
321 5253496 std::copy(list->begin(), list->end(), args);
322
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 5253469 times.
5253498 if (!context_free) {
323
3/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 29 times.
106 for (const Item *arg : make_array(args, arg_count)) {
324 77 add_accum_properties(arg);
325 }
326 }
327 5253498 list->clear(); // Fields are used
328 5253498 return false;
329 }
330
331 5017246 Item_func::Item_func(const POS &pos, PT_item_list *opt_list)
332 5017246 : Item_result_field(pos), allowed_arg_cols(1) {
333
2/2
✓ Branch 0 taken 73975 times.
✓ Branch 1 taken 4943275 times.
5017250 if (opt_list == nullptr) {
334 73975 args = m_embedded_arguments;
335 73975 arg_count = 0;
336 } else
337
1/2
✓ Branch 0 taken 4943277 times.
✗ Branch 1 not taken.
4943275 set_arguments(&opt_list->value, true);
338 5017252 }
339
340 1554873 Item_func::Item_func(THD *thd, const Item_func *item)
341 : Item_result_field(thd, item),
342 1554880 null_on_null(item->null_on_null),
343 1554880 allowed_arg_cols(item->allowed_arg_cols),
344 1554880 used_tables_cache(item->used_tables_cache),
345 1554873 not_null_tables_cache(item->not_null_tables_cache) {
346
2/4
✓ Branch 0 taken 1554878 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1554878 times.
1554880 if (alloc_args(thd->mem_root, item->arg_count)) return;
347
1/2
✓ Branch 0 taken 1554876 times.
✗ Branch 1 not taken.
1554878 std::copy_n(item->args, arg_count, args);
348 }
349
350 36763659 bool Item_func::itemize(Parse_context *pc, Item **res) {
351
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 36763683 times.
36763659 if (skip_itemize(res)) return false;
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36763709 times.
36763683 if (Item_result_field::itemize(pc, res)) return true;
353 36763709 const bool no_named_params = !may_have_named_parameters();
354
2/2
✓ Branch 0 taken 86074573 times.
✓ Branch 1 taken 36763453 times.
122838026 for (size_t i = 0; i < arg_count; i++) {
355 86074573 add_accum_properties(args[i]);
356
2/2
✓ Branch 0 taken 215 times.
✓ Branch 1 taken 86074413 times.
86074575 if (args[i]->itemize(pc, &args[i])) return true;
357
6/6
✓ Branch 0 taken 86043967 times.
✓ Branch 1 taken 30446 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 86043922 times.
✓ Branch 4 taken 43 times.
✓ Branch 5 taken 86074368 times.
86074413 if (no_named_params && !args[i]->item_name.is_autogenerated()) {
358
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 41 times.
43 my_error(functype() == FUNC_SP ? ER_WRONG_PARAMETERS_TO_STORED_FCT
359 : ER_WRONG_PARAMETERS_TO_NATIVE_FCT,
360 43 MYF(0), func_name());
361 43 return true;
362 }
363 }
364 36763453 return false;
365 }
366
367 /*
368 Resolve references to table column for a function and its argument
369
370 SYNOPSIS:
371 fix_fields()
372 thd Thread object
373
374 DESCRIPTION
375 Call fix_fields() for all arguments to the function. The main intention
376 is to allow all Item_field() objects to setup pointers to the table fields.
377
378 Sets as a side effect the following class variables:
379 maybe_null Set if any argument may return NULL
380 used_tables_cache Set to union of the tables used by arguments
381
382 str_value.charset If this is a string function, set this to the
383 character set for the first argument.
384 If any argument is binary, this is set to binary
385
386 If for any item any of the defaults are wrong, then this can
387 be fixed in the resolve_type() function that is called after this one or
388 by writing a specialized fix_fields() for the item.
389
390 RETURN VALUES
391 false ok
392 true Got error. Stored with my_error().
393 */
394
395 47007081 bool Item_func::fix_fields(THD *thd, Item **) {
396
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 47007078 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
47007081 assert(fixed == 0 || basic_const_item());
397
398 Item **arg, **arg_end;
399 uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
400
401 47007081 Condition_context CCT(thd->lex->current_query_block());
402
403
1/2
✓ Branch 0 taken 47007087 times.
✗ Branch 1 not taken.
47007114 used_tables_cache = get_initial_pseudo_tables();
404 47007087 not_null_tables_cache = 0;
405
406 /*
407 Use stack limit of STACK_MIN_SIZE * 2 since
408 on some platforms a recursive call to fix_fields
409 requires more than STACK_MIN_SIZE bytes (e.g. for
410 MIPS, it takes about 22kB to make one recursive
411 call to Item_func::fix_fields())
412 */
413
3/4
✓ Branch 0 taken 47007137 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 47007136 times.
47007087 if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff))
414 1 return true; // Fatal error if flag is set!
415
2/2
✓ Branch 0 taken 45479904 times.
✓ Branch 1 taken 1527232 times.
47007136 if (arg_count) { // Print purify happy
416
2/2
✓ Branch 0 taken 109576946 times.
✓ Branch 1 taken 45475788 times.
155052734 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
417
3/4
✓ Branch 0 taken 109576911 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4081 times.
✓ Branch 3 taken 109572830 times.
109576946 if (fix_func_arg(thd, arg)) return true;
418 }
419 }
420
421
8/10
✓ Branch 0 taken 47003039 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47002611 times.
✓ Branch 3 taken 428 times.
✓ Branch 4 taken 47002618 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 47002604 times.
✓ Branch 8 taken 437 times.
✓ Branch 9 taken 47002609 times.
47003020 if (resolve_type(thd) || thd->is_error()) // Some impls still not error-safe
422 437 return true;
423 47002609 fixed = true;
424 47002609 return false;
425 47007128 }
426
427 109579694 bool Item_func::fix_func_arg(THD *thd, Item **arg) {
428
6/6
✓ Branch 0 taken 55880294 times.
✓ Branch 1 taken 53699400 times.
✓ Branch 2 taken 4065 times.
✓ Branch 3 taken 55876175 times.
✓ Branch 4 taken 4065 times.
✓ Branch 5 taken 109575575 times.
109579694 if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
429 4065 return true; /* purecov: inspected */
430 109575575 Item *item = *arg;
431
432
2/2
✓ Branch 0 taken 96061486 times.
✓ Branch 1 taken 13514089 times.
109575575 if (allowed_arg_cols) {
433
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 96061475 times.
96061486 if (item->check_cols(allowed_arg_cols)) return true;
434 } else {
435 /* we have to fetch allowed_arg_cols from first argument */
436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13514089 times.
13514089 assert(arg == args); // it is first argument
437 13514089 allowed_arg_cols = item->cols();
438
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13514140 times.
13514140 assert(allowed_arg_cols); // Can't be 0 any more
439 }
440
441
4/4
✓ Branch 0 taken 88331246 times.
✓ Branch 1 taken 21244347 times.
✓ Branch 2 taken 17649064 times.
✓ Branch 3 taken 70682245 times.
109575615 set_nullable(is_nullable() || item->is_nullable());
442 109575611 used_tables_cache |= item->used_tables();
443
2/2
✓ Branch 0 taken 79815984 times.
✓ Branch 1 taken 29759595 times.
109575579 if (null_on_null) not_null_tables_cache |= item->not_null_tables();
444 109575581 add_accum_properties(item);
445
446 109575599 return false;
447 }
448
449 27343506 void Item_func::fix_after_pullout(Query_block *parent_query_block,
450 Query_block *removed_query_block) {
451
2/2
✓ Branch 0 taken 447124 times.
✓ Branch 1 taken 26896382 times.
27343506 if (const_item()) {
452 /*
453 Pulling out a const item changes nothing to it. Moreover, some items may
454 have decided that they're const by some other logic than the generic
455 one below, and we must preserve that decision.
456 */
457 447124 return;
458 }
459
460 Item **arg, **arg_end;
461
462 26896382 used_tables_cache = get_initial_pseudo_tables();
463 26896383 not_null_tables_cache = 0;
464
465
2/2
✓ Branch 0 taken 26891788 times.
✓ Branch 1 taken 4595 times.
26896383 if (arg_count) {
466
2/2
✓ Branch 0 taken 72895954 times.
✓ Branch 1 taken 26891780 times.
99787734 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
467 72895954 Item *const item = *arg;
468 72895954 item->fix_after_pullout(parent_query_block, removed_query_block);
469 72895949 used_tables_cache |= item->used_tables();
470
2/2
✓ Branch 0 taken 26770148 times.
✓ Branch 1 taken 46125801 times.
72895949 if (null_on_null) not_null_tables_cache |= item->not_null_tables();
471 }
472 }
473 }
474
475 /**
476 Default implementation for all functions:
477 Propagate base_item's type into all arguments.
478
479 The functions that have context-aware parameter type detection must
480 implement Item::default_data_type() and Item::resolve_type_inner().
481
482 If an SQL function or operator F embeds another SQL function or
483 operator G: F::fix_fields() runs and calls G::fix_fields() which calls
484 G::resolve_type(); assuming that G is outer-context dependent and has only
485 dynamic parameters as arguments, G misses type information and thus does a
486 no-op resolve_type(); then F::fix_fields() continues and calls
487 F::resolve_type() which sees that G::data_type() == MYSQL_TYPE_INVALID;
488 F thus calls G::propagate_type() to send it the necessary type
489 information (i.e. provide the outer context); this then assigns the type
490 to dynamic parameters of G and finishes the job of G::resolve_type() by
491 calling G::resolve_type_inner().
492 */
493 62 bool Item_func::propagate_type(THD *thd, const Type_properties &type) {
494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 assert(data_type() == MYSQL_TYPE_INVALID);
495
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 62 times.
201 for (uint i = 0; i < arg_count; i++) {
496
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 15 times.
139 if (args[i]->data_type() == MYSQL_TYPE_INVALID)
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 if (args[i]->propagate_type(thd, type)) return true;
498 }
499
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
62 if (resolve_type_inner(thd)) return true;
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 assert(data_type() != MYSQL_TYPE_INVALID);
501
502 61 return false;
503 }
504
505 /**
506 For arguments of this Item_func ("args" array), in range
507 [start, start+step, start+2*step,...,end[ : if they're a PS
508 parameter with invalid (not known) type, give them default type "def".
509 @param thd thread handler
510 @param start range's start (included)
511 @param end range's end (excluded)
512 @param step range's step
513 @param def default type
514
515 @returns false if success, true if error
516 */
517 27165601 bool Item_func::param_type_is_default(THD *thd, uint start, uint end, uint step,
518 enum_field_types def) {
519
2/2
✓ Branch 0 taken 38788166 times.
✓ Branch 1 taken 21683098 times.
60471264 for (uint i = start; i < end; i += step) {
520
2/2
✓ Branch 0 taken 5482500 times.
✓ Branch 1 taken 33305666 times.
38788166 if (i >= arg_count) break;
521
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33305663 times.
33305666 if (args[i]->propagate_type(thd, def)) return true;
522 }
523 27165598 return false;
524 }
525
526 /**
527 For arguments of this Item_func ("args" array), in range [start,end[ :
528 sends error if they're a dynamic parameter.
529 @param start range's start (included)
530 @param end range's end (excluded)
531 @returns true if error.
532 */
533 290714 bool Item_func::param_type_is_rejected(uint start, uint end) {
534
2/2
✓ Branch 0 taken 290728 times.
✓ Branch 1 taken 24 times.
290752 for (uint i = start; i < end; i++) {
535
2/2
✓ Branch 0 taken 290687 times.
✓ Branch 1 taken 41 times.
290728 if (i >= arg_count) break;
536
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 38 times.
41 if (args[i]->data_type() == MYSQL_TYPE_INVALID) {
537 3 my_error(ER_INVALID_PARAMETER_USE, MYF(0), "?");
538 3 return true;
539 }
540 }
541 290711 return false;
542 }
543
544 /**
545 For arguments of this Item_func ("args" array), all of them: find an
546 argument that is not a dynamic parameter; if found, all dynamic parameters
547 without a valid type get the type of this; if not found, they get type "def".
548
549 @param thd thread handler
550 @param arg_count number of arguments to check
551 @param args array of arguments, size 'arg_count'
552 @param def default type
553
554 @returns false if success, true if error
555 */
556 26229053 inline bool param_type_uses_non_param_inner(THD *thd, uint arg_count,
557 Item **args, enum_field_types def) {
558 // Use first non-parameter type as base item
559 // @todo If there are multiple non-parameter items, we could use a
560 // consolidated type instead of the first one (consider CASE, COALESCE,
561 // BETWEEN).
562 26229053 uint col_cnt = args[0]->cols();
563
2/2
✓ Branch 0 taken 475 times.
✓ Branch 1 taken 26228583 times.
26229058 if (col_cnt > 1) {
564 /*
565 Row or subquery object: set parameter type recursively for the ith
566 Item in each argument row.
567 */
568
1/2
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
475 Item **arguments = new (*THR_MALLOC) Item *[arg_count];
569
2/2
✓ Branch 0 taken 1058 times.
✓ Branch 1 taken 458 times.
1516 for (uint i = 0; i < col_cnt; i++) {
570
2/2
✓ Branch 0 taken 2848 times.
✓ Branch 1 taken 1050 times.
3898 for (uint j = 0; j < arg_count; j++) {
571
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2840 times.
2848 if (args[j]->cols() != col_cnt) // Column count not checked yet
572 8 return false;
573
2/2
✓ Branch 0 taken 2770 times.
✓ Branch 1 taken 70 times.
2840 if (args[j]->type() == Item::ROW_ITEM)
574 2770 arguments[j] = down_cast<Item_row *>(args[j])->element_index(i);
575
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 else if (args[j]->type() == Item::SUBSELECT_ITEM)
576 70 arguments[j] = (*down_cast<Item_subselect *>(args[j])
577 70 ->unit->get_unit_column_types())[i];
578 }
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1050 times.
1050 if (param_type_uses_non_param_inner(thd, arg_count, arguments, def))
580 return true;
581 }
582 // Resolving for row done, set data type to MYSQL_TYPE_NULL as final action.
583
2/2
✓ Branch 0 taken 1235 times.
✓ Branch 1 taken 458 times.
1693 for (uint j = 0; j < arg_count; j++)
584 1235 args[j]->set_data_type(MYSQL_TYPE_NULL);
585 458 return false;
586 }
587 26228583 Item *base_item = nullptr;
588
2/2
✓ Branch 0 taken 26229387 times.
✓ Branch 1 taken 138 times.
26229525 for (uint i = 0; i < arg_count; i++) {
589
2/2
✓ Branch 0 taken 26228445 times.
✓ Branch 1 taken 942 times.
26229387 if (args[i]->data_type() != MYSQL_TYPE_INVALID) {
590 26228445 base_item = args[i];
591 26228445 break;
592 }
593 }
594
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 26228441 times.
26228583 if (base_item == nullptr) {
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (args[0]->propagate_type(thd, def)) return true;
596 142 base_item = args[0];
597 }
598
2/2
✓ Branch 0 taken 54515077 times.
✓ Branch 1 taken 26228598 times.
80743675 for (uint i = 0; i < arg_count; i++) {
599
2/2
✓ Branch 0 taken 54512186 times.
✓ Branch 1 taken 2900 times.
54515077 if (args[i]->data_type() != MYSQL_TYPE_INVALID) continue;
600
2/4
✓ Branch 0 taken 2906 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2906 times.
2900 if (args[i]->propagate_type(thd, Type_properties(*base_item))) return true;
601 }
602 26228598 return false;
603 }
604
605 31461507 bool Item_func::param_type_uses_non_param(THD *thd, enum_field_types def) {
606
2/2
✓ Branch 0 taken 5233508 times.
✓ Branch 1 taken 26227999 times.
31461507 if (arg_count == 0) return false;
607 26227999 return param_type_uses_non_param_inner(thd, arg_count, args, def);
608 }
609
610 50268042 bool Item_func::walk(Item_processor processor, enum_walk walk,
611 uchar *argument) {
612
8/8
✓ Branch 0 taken 18295658 times.
✓ Branch 1 taken 31973249 times.
✓ Branch 2 taken 13388729 times.
✓ Branch 3 taken 4906929 times.
✓ Branch 4 taken 41 times.
✓ Branch 5 taken 18295500 times.
✓ Branch 6 taken 41 times.
✓ Branch 7 taken 50268749 times.
50268042 if ((walk & enum_walk::PREFIX) && (this->*processor)(argument)) return true;
613
614 Item **arg, **arg_end;
615
2/2
✓ Branch 0 taken 121685742 times.
✓ Branch 1 taken 50262766 times.
171948508 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
616
2/2
✓ Branch 0 taken 6216 times.
✓ Branch 1 taken 121679759 times.
121685742 if ((*arg)->walk(processor, walk, argument)) return true;
617 }
618
6/6
✓ Branch 0 taken 32518430 times.
✓ Branch 1 taken 17744645 times.
✓ Branch 2 taken 27823569 times.
✓ Branch 3 taken 4694861 times.
✓ Branch 4 taken 1040 times.
✓ Branch 5 taken 32517366 times.
50262766 return (walk & enum_walk::POSTFIX) && (this->*processor)(argument);
619 }
620
621 void Item_func::traverse_cond(Cond_traverser traverser, void *argument,
622 traverse_order order) {
623 if (arg_count) {
624 Item **arg, **arg_end;
625
626 switch (order) {
627 case (PREFIX):
628 (*traverser)(this, argument);
629 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
630 (*arg)->traverse_cond(traverser, argument, order);
631 }
632 break;
633 case (POSTFIX):
634 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
635 (*arg)->traverse_cond(traverser, argument, order);
636 }
637 (*traverser)(this, argument);
638 }
639 } else
640 (*traverser)(this, argument);
641 }
642
643 /**
644 Transform an Item_func object with a transformer callback function.
645
646 The function recursively applies the transform method to each
647 argument of the Item_func node.
648 If the call of the method for an argument item returns a new item
649 the old item is substituted for a new one.
650 After this the transformer is applied to the root node
651 of the Item_func object.
652 */
653
654 968591 Item *Item_func::transform(Item_transformer transformer, uchar *argument) {
655
2/2
✓ Branch 0 taken 118623 times.
✓ Branch 1 taken 849968 times.
968591 if (arg_count) {
656 Item **arg, **arg_end;
657
2/2
✓ Branch 0 taken 237629 times.
✓ Branch 1 taken 118623 times.
356252 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
658 237629 *arg = (*arg)->transform(transformer, argument);
659
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 237629 times.
237629 if (*arg == nullptr) return nullptr; /* purecov: inspected */
660 }
661 }
662
2/2
✓ Branch 0 taken 126482 times.
✓ Branch 1 taken 842109 times.
968591 return (this->*transformer)(argument);
663 }
664
665 /**
666 Compile Item_func object with a processor and a transformer
667 callback functions.
668
669 First the function applies the analyzer to the root node of
670 the Item_func object. Then if the analyzer succeeeds (returns true)
671 the function recursively applies the compile method to each argument
672 of the Item_func node.
673 If the call of the method for an argument item returns a new item
674 the old item is substituted for a new one.
675 After this the transformer is applied to the root node
676 of the Item_func object.
677 */
678
679 9376729 Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
680 Item_transformer transformer, uchar *arg_t) {
681
4/4
✓ Branch 0 taken 6495600 times.
✓ Branch 1 taken 2881129 times.
✓ Branch 2 taken 9282 times.
✓ Branch 3 taken 9367463 times.
9376729 if (!(this->*analyzer)(arg_p)) return this;
682
2/2
✓ Branch 0 taken 9207678 times.
✓ Branch 1 taken 159785 times.
9367463 if (arg_count) {
683 Item **arg, **arg_end;
684
2/2
✓ Branch 0 taken 19928500 times.
✓ Branch 1 taken 9207694 times.
29136194 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++) {
685 /*
686 The same parameter value of arg_p must be passed
687 to analyze any argument of the condition formula.
688 */
689 19928500 uchar *arg_v = *arg_p;
690
1/2
✓ Branch 0 taken 19928498 times.
✗ Branch 1 not taken.
19928500 Item *new_item = (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
691
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 19928496 times.
19928498 if (new_item == nullptr) return nullptr;
692
4/6
✓ Branch 0 taken 148155 times.
✓ Branch 1 taken 19780341 times.
✓ Branch 2 taken 148155 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 148175 times.
✗ Branch 5 not taken.
19928496 if (*arg != new_item) current_thd->change_item_tree(arg, new_item);
693 }
694 }
695
2/2
✓ Branch 0 taken 5789621 times.
✓ Branch 1 taken 3577858 times.
9367479 return (this->*transformer)(arg_t);
696 }
697
698 /**
699 See comments in Item_cmp_func::split_sum_func()
700 */
701
702 402328 void Item_func::split_sum_func(THD *thd, Ref_item_array ref_item_array,
703 mem_root_deque<Item *> *fields) {
704 Item **arg, **arg_end;
705
2/2
✓ Branch 0 taken 746387 times.
✓ Branch 1 taken 402328 times.
1148715 for (arg = args, arg_end = args + arg_count; arg != arg_end; arg++)
706 746387 (*arg)->split_sum_func2(thd, ref_item_array, fields, arg, true);
707 402328 }
708
709 57235471 void Item_func::update_used_tables() {
710 57235471 used_tables_cache = get_initial_pseudo_tables();
711 57235747 not_null_tables_cache = 0;
712
713
2/2
✓ Branch 0 taken 120936409 times.
✓ Branch 1 taken 57235702 times.
178172111 for (uint i = 0; i < arg_count; i++) {
714 120936409 args[i]->update_used_tables();
715 120936187 used_tables_cache |= args[i]->used_tables();
716
2/2
✓ Branch 0 taken 112752972 times.
✓ Branch 1 taken 8183366 times.
120936338 if (null_on_null) not_null_tables_cache |= args[i]->not_null_tables();
717 120936454 add_accum_properties(args[i]);
718 }
719 57235702 }
720
721 1693985 void Item_func::print(const THD *thd, String *str,
722 enum_query_type query_type) const {
723
1/2
✓ Branch 0 taken 1693986 times.
✗ Branch 1 not taken.
1693985 str->append(func_name());
724 1693986 str->append('(');
725 1693985 print_args(thd, str, 0, query_type);
726 1693985 str->append(')');
727 1693985 }
728
729 1755967 void Item_func::print_args(const THD *thd, String *str, uint from,
730 enum_query_type query_type) const {
731
2/2
✓ Branch 0 taken 3893772 times.
✓ Branch 1 taken 1755967 times.
5649739 for (uint i = from; i < arg_count; i++) {
732
2/2
✓ Branch 0 taken 2215068 times.
✓ Branch 1 taken 1678704 times.
3893772 if (i != from) str->append(',');
733 3893772 args[i]->print(thd, str, query_type);
734 }
735 1755967 }
736
737 1183285 void Item_func::print_op(const THD *thd, String *str,
738 enum_query_type query_type) const {
739 1183285 str->append('(');
740
2/2
✓ Branch 0 taken 1183285 times.
✓ Branch 1 taken 1183286 times.
2366571 for (uint i = 0; i < arg_count - 1; i++) {
741 1183285 args[i]->print(thd, str, query_type);
742 1183286 str->append(' ');
743
1/2
✓ Branch 0 taken 1183286 times.
✗ Branch 1 not taken.
1183286 str->append(func_name());
744 1183286 str->append(' ');
745 }
746 1183286 args[arg_count - 1]->print(thd, str, query_type);
747 1183286 str->append(')');
748 1183286 }
749
750 /// @note Please keep in sync with Item_sum::eq().
751 501750 bool Item_func::eq(const Item *item, bool binary_cmp) const {
752 /* Assume we don't have rtti */
753
2/2
✓ Branch 0 taken 71271 times.
✓ Branch 1 taken 430479 times.
501750 if (this == item) return true;
754
2/2
✓ Branch 0 taken 178271 times.
✓ Branch 1 taken 252209 times.
430479 if (item->type() != FUNC_ITEM) return false;
755 252209 const Item_func *item_func = down_cast<const Item_func *>(item);
756 Item_func::Functype func_type;
757 252209 if ((func_type = functype()) != item_func->functype() ||
758
4/4
✓ Branch 0 taken 155539 times.
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 154509 times.
✓ Branch 3 taken 1030 times.
155859 arg_count != item_func->arg_count ||
759 154509 (func_type != Item_func::FUNC_SP &&
760
8/8
✓ Branch 0 taken 155859 times.
✓ Branch 1 taken 96350 times.
✓ Branch 2 taken 151691 times.
✓ Branch 3 taken 2818 times.
✓ Branch 4 taken 1030 times.
✓ Branch 5 taken 151691 times.
✓ Branch 6 taken 100006 times.
✓ Branch 7 taken 152203 times.
409098 strcmp(func_name(), item_func->func_name()) != 0) ||
761 1030 (func_type == Item_func::FUNC_SP &&
762
2/2
✓ Branch 0 taken 518 times.
✓ Branch 1 taken 512 times.
1030 my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
763 100006 return false;
764 152203 return AllItemsAreEqual(args, item_func->args, arg_count, binary_cmp);
765 }
766
767 68275 Field *Item_func::tmp_table_field(TABLE *table) {
768 68275 Field *field = nullptr;
769
770
3/5
✓ Branch 0 taken 6370 times.
✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 61780 times.
✗ Branch 4 not taken.
68275 switch (result_type()) {
771 6370 case INT_RESULT:
772
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6369 times.
6370 if (this->data_type() == MYSQL_TYPE_YEAR)
773
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 field = new (*THR_MALLOC) Field_year(is_nullable(), item_name.ptr());
774
2/2
✓ Branch 0 taken 2164 times.
✓ Branch 1 taken 4205 times.
6369 else if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
775
1/2
✓ Branch 0 taken 2164 times.
✗ Branch 1 not taken.
6492 field = new (*THR_MALLOC) Field_longlong(
776
1/2
✓ Branch 0 taken 2164 times.
✗ Branch 1 not taken.
6492 max_length, is_nullable(), item_name.ptr(), unsigned_flag);
777 else
778
1/2
✓ Branch 0 taken 4205 times.
✗ Branch 1 not taken.
16820 field = new (*THR_MALLOC) Field_long(max_length, is_nullable(),
779
1/2
✓ Branch 0 taken 4205 times.
✗ Branch 1 not taken.
12615 item_name.ptr(), unsigned_flag);
780 6370 break;
781 125 case REAL_RESULT:
782
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 122 times.
125 if (this->data_type() == MYSQL_TYPE_FLOAT) {
783
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
9 field = new (*THR_MALLOC)
784 3 Field_float(max_char_length(), is_nullable(), item_name.ptr(),
785
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 decimals, unsigned_flag);
786 } else {
787
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
366 field = new (*THR_MALLOC)
788 122 Field_double(max_char_length(), is_nullable(), item_name.ptr(),
789
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
244 decimals, unsigned_flag);
790 }
791 125 break;
792 case STRING_RESULT:
793 return make_string_field(table);
794 break;
795 61780 case DECIMAL_RESULT:
796 61780 field = Field_new_decimal::create_from_item(this);
797 61780 break;
798 case ROW_RESULT:
799 default:
800 // This case should never be chosen
801 assert(0);
802 field = nullptr;
803 break;
804 }
805
1/2
✓ Branch 0 taken 68275 times.
✗ Branch 1 not taken.
68275 if (field) field->init(table);
806 68275 return field;
807 }
808
809 1335759 my_decimal *Item_func::val_decimal(my_decimal *decimal_value) {
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1335759 times.
1335759 assert(fixed);
811 1335759 longlong nr = val_int();
812
2/2
✓ Branch 0 taken 599270 times.
✓ Branch 1 taken 736489 times.
1335759 if (null_value) return nullptr; /* purecov: inspected */
813 736489 int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
814 736489 return decimal_value;
815 }
816
817 518601 String *Item_real_func::val_str(String *str) {
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 518601 times.
518601 assert(fixed == 1);
819 518601 double nr = val_real();
820
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 518750 times.
518758 if (null_value) return nullptr; /* purecov: inspected */
821 518750 str->set_real(nr, decimals, collation.collation);
822 519232 return str;
823 }
824
825 10 my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) {
826
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 assert(fixed);
827 10 double nr = val_real();
828
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (null_value) return nullptr; /* purecov: inspected */
829 5 double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
830 5 return decimal_value;
831 }
832
833 96 void Item_func::fix_num_length_and_dec() {
834 96 uint fl_length = 0;
835 96 decimals = 0;
836
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 96 times.
208 for (uint i = 0; i < arg_count; i++) {
837 112 decimals = max(decimals, args[i]->decimals);
838 112 fl_length = max(fl_length, args[i]->max_length);
839 }
840 96 max_length = float_length(decimals);
841
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 94 times.
96 if (fl_length > max_length) {
842 2 decimals = DECIMAL_NOT_SPECIFIED;
843 2 max_length = float_length(DECIMAL_NOT_SPECIFIED);
844 }
845 96 }
846
847 4220665 void Item_func_numhybrid::fix_num_length_and_dec() {}
848
849 14795 void Item_func::signal_divide_by_null() {
850 14795 THD *thd = current_thd;
851
2/2
✓ Branch 0 taken 10469 times.
✓ Branch 1 taken 4326 times.
14795 if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
852 10469 push_warning(thd, Sql_condition::SL_WARNING, ER_DIVISION_BY_ZERO,
853 ER_THD(thd, ER_DIVISION_BY_ZERO));
854 14795 null_value = true;
855 14795 }
856
857 60 void Item_func::signal_invalid_argument_for_log() {
858 60 THD *thd = current_thd;
859 60 push_warning(thd, Sql_condition::SL_WARNING,
860 ER_INVALID_ARGUMENT_FOR_LOGARITHM,
861 ER_THD(thd, ER_INVALID_ARGUMENT_FOR_LOGARITHM));
862 60 null_value = true;
863 60 }
864
865 62861 Item *Item_func::get_tmp_table_item(THD *thd) {
866
1/2
✓ Branch 0 taken 62861 times.
✗ Branch 1 not taken.
62861 DBUG_TRACE;
867
868 /*
869 For items with aggregate functions, return the copy
870 of the function.
871 For constant items, return the same object, as fields
872 are not created in temp tables for them.
873 For items with windowing functions, return the same
874 object (temp table fields are not created for windowing
875 functions if they are not evaluated at this stage).
876 */
877
6/6
✓ Branch 0 taken 62603 times.
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 62540 times.
✓ Branch 3 taken 63 times.
✓ Branch 4 taken 61214 times.
✓ Branch 5 taken 1647 times.
125401 if (!has_aggregation() && !has_wf() &&
878
3/4
✓ Branch 0 taken 62540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1326 times.
✓ Branch 3 taken 61214 times.
62540 !(const_for_execution() &&
879
2/4
✓ Branch 0 taken 1326 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1326 times.
1326 evaluate_during_optimization(this, thd->lex->current_query_block()))) {
880
2/4
✓ Branch 0 taken 61214 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 61214 times.
✗ Branch 3 not taken.
61214 Item *result = new Item_field(result_field);
881 61214 return result;
882 }
883
1/2
✓ Branch 0 taken 1647 times.
✗ Branch 1 not taken.
1647 Item *result = copy_or_same(thd);
884 1647 return result;
885 62861 }
886
887 62827831 const Item_field *Item_func::contributes_to_filter(
888 table_map read_tables, table_map filter_for_table,
889 const MY_BITMAP *fields_to_ignore) const {
890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62827831 times.
62827831 assert((read_tables & filter_for_table) == 0);
891 /*
892 Multiple equality (Item_equal) should not call this function
893 because it would reject valid comparisons.
894 */
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62827900 times.
62827831 assert(functype() != MULT_EQUAL_FUNC);
896
897 /*
898 To contribute to filtering effect, the condition must refer to
899 exactly one unread table: the table filtering is currently
900 calculated for.
901 */
902
2/2
✓ Branch 0 taken 52806879 times.
✓ Branch 1 taken 10021023 times.
62827900 if ((used_tables() & ~read_tables) != filter_for_table) return nullptr;
903
904 /*
905 Whether or not this Item_func has an operand that is a field in
906 'filter_for_table' that is not in 'fields_to_ignore'.
907 */
908 10021023 Item_field *usable_field = nullptr;
909
910 /*
911 Whether or not this Item_func has an operand that can be used as
912 available value. arg_count==1 for Items with implicit values like
913 "field IS NULL".
914 */
915 10021023 bool found_comparable = (arg_count == 1);
916
917
2/2
✓ Branch 0 taken 20004088 times.
✓ Branch 1 taken 10020673 times.
30024761 for (uint i = 0; i < arg_count; i++) {
918 20004088 const Item::Type arg_type = args[i]->real_item()->type();
919
920
2/2
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 20003661 times.
20004096 if (arg_type == Item::SUBSELECT_ITEM) {
921
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 349 times.
435 if (args[i]->const_for_execution()) {
922 // Constant subquery, i.e., not a dependent subquery.
923 86 found_comparable = true;
924 86 continue;
925 }
926
927 /*
928 This is either "fld OP <dependent_subquery>" or "fld BETWEEN X
929 and Y" where either X or Y is a dependent subquery. Filtering
930 effect should not be calculated for this item because the cost
931 of evaluating the dependent subquery is currently not
932 calculated and its accompanying filtering effect is too
933 uncertain. See WL#7384.
934 */
935 349 return nullptr;
936 } // ... if subquery.
937
938 20003661 const table_map used_tabs = args[i]->used_tables();
939
940
4/4
✓ Branch 0 taken 4119171 times.
✓ Branch 1 taken 15884481 times.
✓ Branch 2 taken 4025888 times.
✓ Branch 3 taken 93283 times.
20003652 if (arg_type == Item::FIELD_ITEM && (used_tabs == filter_for_table)) {
941 /*
942 The qualifying table of args[i] is filter_for_table. args[i]
943 may be a field or a reference to a field, e.g. through a
944 view.
945 */
946 4025888 Item_field *fld = static_cast<Item_field *>(args[i]->real_item());
947
948 /*
949 Use args[i] as value if
950 1) this field shall be ignored, or
951 2) a usable field has already been found (meaning that
952 this is "filter_for_table.colX OP filter_for_table.colY").
953 */
954
6/6
✓ Branch 0 taken 4003273 times.
✓ Branch 1 taken 22615 times.
✓ Branch 2 taken 284 times.
✓ Branch 3 taken 4002989 times.
✓ Branch 4 taken 22899 times.
✓ Branch 5 taken 4002989 times.
4025888 if (bitmap_is_set(fields_to_ignore, fld->field->field_index()) || // 1)
955 usable_field) // 2)
956 {
957 22899 found_comparable = true;
958 22899 continue;
959 }
960
961 /*
962 This field shall contribute to filtering effect if a
963 value is found for it
964 */
965 4002989 usable_field = fld;
966 4002989 } // if field.
967 else {
968 /*
969 It's not a subquery. May be a function, a constant, an outer
970 reference, a field of another table...
971
972 Already checked that this predicate does not refer to tables
973 later in the join sequence. Verify it:
974 */
975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15977764 times.
15977764 assert(!(used_tabs & (~read_tables & ~filter_for_table)));
976 15977764 found_comparable = true;
977 }
978 }
979
1/2
✓ Branch 0 taken 10020729 times.
✗ Branch 1 not taken.
10020673 return (found_comparable ? usable_field : nullptr);
980 }
981
982 118074 bool Item_func::is_valid_for_pushdown(uchar *arg) {
983 Condition_pushdown::Derived_table_info *dti =
984 118074 pointer_cast<Condition_pushdown::Derived_table_info *>(arg);
985 // We cannot push conditions that are not deterministic to a
986 // derived table having set operations.
987
4/4
✓ Branch 0 taken 170 times.
✓ Branch 1 taken 117904 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 164 times.
118074 return (dti->is_set_operation() && is_non_deterministic());
988 }
989
990 43 bool Item_func::check_column_in_window_functions(uchar *arg [[maybe_unused]]) {
991 // Pushing conditions having non-deterministic results must be done with
992 // care, or it may result in eliminating rows which would have
993 // otherwise contributed to aggregations.
994 // For Ex: SELECT * FROM (SELECT a AS x, SUM(b) FROM t1 GROUP BY a) dt
995 // WHERE x>5*RAND() AND x<3.
996 // In this case, x<3 is pushed to the WHERE clause of the derived table
997 // because there is grouping on "a". If we did the same for the random
998 // condition, this condition might reduce the number of rows that get
999 // qualified for grouping, resulting in wrong values for SUM. Similarly for
1000 // window functions. So we refrain from pushing the random condition
1001 // past the last operation done in the derived table's
1002 // materialization. Therefore, if there are window functions we cannot push
1003 // to HAVING, and if there is GROUP BY we cannot push to WHERE.
1004 // See also Item_field::is_valid_for_pushdown().
1005 43 return is_non_deterministic();
1006 }
1007
1008 72 bool Item_func::check_column_in_group_by(uchar *arg [[maybe_unused]]) {
1009 72 return is_non_deterministic();
1010 }
1011
1012 170704 bool is_function_of_type(const Item *item, Item_func::Functype type) {
1013
2/2
✓ Branch 0 taken 46795 times.
✓ Branch 1 taken 123909 times.
217499 return item->type() == Item::FUNC_ITEM &&
1014
2/2
✓ Branch 0 taken 4983 times.
✓ Branch 1 taken 41812 times.
217499 down_cast<const Item_func *>(item)->functype() == type;
1015 }
1016
1017 99 bool contains_function_of_type(Item *item, Item_func::Functype type) {
1018
1/2
✓ Branch 0 taken 99 times.
✗ Branch 1 not taken.
198 return WalkItem(item, enum_walk::PREFIX, [type](Item *inner_item) {
1019 187 return is_function_of_type(inner_item, type);
1020 198 });
1021 }
1022
1023 /**
1024 Return new Item_field if given expression matches GC
1025
1026 @see substitute_gc()
1027
1028 @param func Expression to be replaced
1029 @param fld GCs field
1030 @param type Result type to match with Field
1031 @param[out] found If given, just return found field, without Item_field
1032
1033 @returns
1034 item new Item_field for matched GC
1035 NULL otherwise
1036 */
1037
1038 1147 Item_field *get_gc_for_expr(const Item *func, Field *fld, Item_result type,
1039 Field **found) {
1040 1147 func = func->real_item();
1041 1147 Item *expr = fld->gcol_info->expr_item;
1042
1043 /*
1044 In the case where the generated column expression returns JSON and
1045 the predicate compares the values as strings, it is not safe to
1046 replace the expression with the generated column, since the
1047 indexed string values will be double-quoted. The generated column
1048 expression should use the JSON_UNQUOTE function to strip off the
1049 double-quotes in order to get a usable index for looking up
1050 strings. See also the comment below.
1051 */
1052
4/6
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 346 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 801 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1147 times.
1147 if (type == STRING_RESULT && expr->data_type() == MYSQL_TYPE_JSON)
1053 return nullptr;
1054
1055 /*
1056 In order to match expressions against a functional index's expression,
1057 it's needed to skip CAST(.. AS .. ) and potentially COLLATE from the latter.
1058 This can't be joined with striping json_unquote below, since we might need
1059 to skip it too in expression like:
1060 CAST(JSON_UNQUOTE(<expr>) AS CHAR(X))
1061
1062 Also skip unquoting function. This is needed to address JSON string
1063 comparison issue. All JSON_* functions return quoted strings. In
1064 order to create usable index, GC column expression has to include
1065 JSON_UNQUOTE function, e.g JSON_UNQUOTE(JSON_EXTRACT(..)).
1066 Hence, the unquoting function in column expression have to be
1067 skipped in order to correctly match GC expr to expr in
1068 WHERE condition. The exception is if user has explicitly used
1069 JSON_UNQUOTE in WHERE condition.
1070 */
1071
1072 4588 for (Item_func::Functype functype :
1073 {Item_func::COLLATE_FUNC, Item_func::TYPECAST_FUNC,
1074
2/2
✓ Branch 0 taken 3441 times.
✓ Branch 1 taken 1147 times.
5735 Item_func::JSON_UNQUOTE_FUNC}) {
1075
5/6
✓ Branch 0 taken 3441 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1098 times.
✓ Branch 3 taken 2343 times.
✓ Branch 4 taken 1013 times.
✓ Branch 5 taken 2428 times.
4539 if (is_function_of_type(expr, functype) &&
1076
3/4
✓ Branch 0 taken 1098 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1013 times.
✓ Branch 3 taken 85 times.
1098 !is_function_of_type(func, functype)) {
1077
1/2
✓ Branch 0 taken 1013 times.
✗ Branch 1 not taken.
1013 expr = down_cast<Item_func *>(expr)->get_arg(0);
1078 }
1079 }
1080
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1147 times.
1147 if (!expr->can_be_substituted_for_gc(fld->is_array())) {
1082 return nullptr;
1083 }
1084
1085 // JSON implementation always uses binary collation
1086 1147 bool bin_cmp = (expr->data_type() == MYSQL_TYPE_JSON);
1087
6/6
✓ Branch 0 taken 1035 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 847 times.
✓ Branch 3 taken 188 times.
✓ Branch 4 taken 847 times.
✓ Branch 5 taken 300 times.
1147 if (type == fld->result_type() && func->eq(expr, bin_cmp)) {
1088
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 613 times.
847 if (found) {
1089 // Temporary mark the field in order to check correct value conversion
1090 234 fld->table->mark_column_used(fld, MARK_COLUMNS_TEMP);
1091 234 *found = fld;
1092 234 return nullptr;
1093 }
1094 // Mark field for read
1095 613 fld->table->mark_column_used(fld, MARK_COLUMNS_READ);
1096
2/4
✓ Branch 0 taken 613 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 613 times.
✗ Branch 3 not taken.
613 Item_field *field = new Item_field(fld);
1097 613 return field;
1098 }
1099
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 251 times.
300 if (found) *found = nullptr;
1100 300 return nullptr;
1101 }
1102
1103 /**
1104 Attempt to substitute an expression with an equivalent generated
1105 column in a predicate.
1106
1107 @param expr the expression that should be substituted
1108 @param value if given, value will be coerced to GC field's type and
1109 the result will substitute the original value. Used by
1110 multi-valued index.
1111 @param gc_fields list of indexed generated columns to check for
1112 equivalence with the expression
1113 @param type the acceptable type of the generated column that
1114 replaces the expression
1115 @param predicate the predicate in which the substitution is done
1116
1117 @return true on error, false on success
1118 */
1119 762 static bool substitute_gc_expression(Item **expr, Item **value,
1120 List<Field> *gc_fields, Item_result type,
1121 Item_func *predicate) {
1122
1/2
✓ Branch 0 taken 762 times.
✗ Branch 1 not taken.
762 List_iterator<Field> li(*gc_fields);
1123 762 Item_field *item_field = nullptr;
1124
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 150 times.
1024 while (Field *field = li++) {
1125 // Check whether the field has usable keys.
1126 874 Key_map tkm = field->part_of_key;
1127 874 tkm.merge(field->part_of_prefixkey); // Include prefix keys.
1128 874 tkm.intersect(field->table->keys_in_use_for_query);
1129 /*
1130 Don't substitute if:
1131 1) Key is disabled
1132 2) It's a multi-valued index's field and predicate isn't MEMBER OF
1133 */
1134
4/4
✓ Branch 0 taken 860 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 856 times.
1734 if (tkm.is_clear_all() || // (1)
1135
6/8
✓ Branch 0 taken 860 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 552 times.
✓ Branch 3 taken 308 times.
✓ Branch 4 taken 552 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 548 times.
860 (field->is_array() && predicate->functype() != // (2)
1136 Item_func::MEMBER_OF_FUNC))
1137 18 continue;
1138 // If the field is a hidden field used by a functional index, we require
1139 // that the collation of the field must match the collation of the
1140 // expression. If not, we might end up with the wrong result when using
1141 // the index (see bug#27337092). Ideally, this should be done for normal
1142 // generated columns as well, but that is delayed to a later fix since the
1143 // impact might be quite large.
1144
4/4
✓ Branch 0 taken 617 times.
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 851 times.
✓ Branch 3 taken 5 times.
1473 if (!(field->is_field_for_functional_index() &&
1145
3/4
✓ Branch 0 taken 617 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 599 times.
617 field->match_collation_to_optimize_range() &&
1146
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 5 times.
18 (*expr)->collation.collation != field->charset())) {
1147
1/2
✓ Branch 0 taken 851 times.
✗ Branch 1 not taken.
851 item_field = get_gc_for_expr(*expr, field, type);
1148
2/2
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 239 times.
851 if (item_field != nullptr) break;
1149 }
1150 262 }
1151
1152
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 612 times.
762 if (item_field == nullptr) return false;
1153
1154 // A matching expression is found. Substitute the expression with
1155 // the matching generated column.
1156
1/2
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
612 THD *thd = current_thd;
1157
6/8
✓ Branch 0 taken 612 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 464 times.
✓ Branch 3 taken 148 times.
✓ Branch 4 taken 464 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 464 times.
✓ Branch 7 taken 148 times.
612 if (item_field->returns_array() && value) {
1158 464 Json_wrapper wr;
1159 464 String str_val, buf;
1160 464 Field_typed_array *afld = down_cast<Field_typed_array *>(item_field->field);
1161
1162
1/2
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
464 Functional_index_error_handler functional_index_error_handler(afld, thd);
1163
1164
2/4
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 464 times.
464 if (get_json_atom_wrapper(value, 0, "MEMBER OF", &str_val, &buf, &wr,
1165 nullptr, true))
1166 return true;
1167
1168 464 auto to_wr = make_unique_destroy_only<Json_wrapper>(thd->mem_root);
1169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 464 times.
464 if (to_wr == nullptr) return true;
1170
1171 // Don't substitute if value can't be coerced to field's type
1172
3/4
✓ Branch 0 taken 464 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 462 times.
464 if (afld->coerce_json_value(&wr, /*no_error=*/true, to_wr.get()))
1173 2 return false;
1174
1175 Item_json *jsn =
1176
2/4
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✗ Branch 3 not taken.
462 new (thd->mem_root) Item_json(std::move(to_wr), predicate->item_name);
1177
4/8
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 462 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 462 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 462 times.
462 if (jsn == nullptr || jsn->fix_fields(thd, nullptr)) return true;
1178
1/2
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
462 thd->change_item_tree(value, jsn);
1179
10/10
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 462 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 462 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 462 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 462 times.
✓ Branch 9 taken 2 times.
472 }
1180
1/2
✓ Branch 0 taken 610 times.
✗ Branch 1 not taken.
610 thd->change_item_tree(expr, item_field);
1181
1182 // Adjust the predicate.
1183
1/2
✓ Branch 0 taken 610 times.
✗ Branch 1 not taken.
610 return predicate->resolve_type(thd);
1184 }
1185
1186 /**
1187 A helper function for Item_func::gc_subst_transformer, that tries to
1188 substitute the given JSON_CONTAINS or JSON_OVERLAPS function for one of GCs
1189 from the provided list. The function checks whether there's an index with
1190 matching expression and whether all scalars for lookup can be coerced to
1191 index's GC field without errors. If so, index's GC field substitutes the
1192 given function, args are replaced for array of coerced values in order to
1193 match GC's type. substitute_gc_expression() can't be used to these functions
1194 as it's tailored to handle regular single-valued indexes and doesn't ensure
1195 correct coercion of all values to lookup in multi-valued index.
1196
1197 @param func Function to replace
1198 @param vals Args to replace
1199 @param vals_wr Json_wrapper containing array of values for index lookup
1200 @param gc_fields List of generated fields to look the function's substitute in
1201 */
1202
1203 257 static void gc_subst_overlaps_contains(Item **func, Item **vals,
1204 Json_wrapper &vals_wr,
1205 List<Field> *gc_fields) {
1206 // Field to substitute function for. NULL when no matching index was found.
1207 257 Field *found = nullptr;
1208
4/8
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 257 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 257 times.
✗ Branch 7 not taken.
257 assert(vals_wr.type() != enum_json_type::J_OBJECT &&
1209 vals_wr.type() != enum_json_type::J_ERROR);
1210
1/2
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
257 THD *thd = current_thd;
1211 // Vector of coerced keys
1212
1/2
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
257 Json_array_ptr coerced_keys = create_dom_ptr<Json_array>();
1213
1214 // Find a field that matches the expression
1215
5/8
✓ Branch 0 taken 257 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 257 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 395 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 369 times.
✓ Branch 7 taken 26 times.
395 for (Field &fld : *gc_fields) {
1216 369 bool can_use_index = true;
1217 // Check whether field has usable keys
1218 369 Key_map tkm = fld.part_of_key;
1219 369 tkm.intersect(fld.table->keys_in_use_for_query);
1220
1221
7/8
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 356 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 283 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 283 times.
418 if (tkm.is_clear_all() || !fld.is_array()) continue;
1222
1/2
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
283 Functional_index_error_handler func_idx_err_hndl(&fld, thd);
1223 283 found = nullptr;
1224
1225
2/4
✓ Branch 0 taken 283 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 283 times.
✗ Branch 3 not taken.
283 get_gc_for_expr(*func, &fld, fld.result_type(), &found);
1226
6/8
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 234 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 234 times.
✓ Branch 6 taken 49 times.
✓ Branch 7 taken 234 times.
283 if (!found || !found->is_array()) continue;
1227 234 Field_typed_array *afld = down_cast<Field_typed_array *>(found);
1228 // Check that array's values can be coerced to found field's type
1229 uint len;
1230
3/4
✓ Branch 0 taken 234 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 92 times.
234 if (vals_wr.type() == enum_json_type::J_ARRAY)
1231
1/2
✓ Branch 0 taken 142 times.
✗ Branch 1 not taken.
142 len = vals_wr.length();
1232 else
1233 92 len = 1;
1234 234 coerced_keys->clear();
1235
2/2
✓ Branch 0 taken 377 times.
✓ Branch 1 taken 231 times.
608 for (uint i = 0; i < len; i++) {
1236
1/2
✓ Branch 0 taken 377 times.
✗ Branch 1 not taken.
377 Json_wrapper elt = vals_wr[i];
1237 377 Json_wrapper res;
1238
3/4
✓ Branch 0 taken 377 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 374 times.
377 if (afld->coerce_json_value(&elt, true, &res)) {
1239 3 can_use_index = false;
1240 3 found = nullptr;
1241 3 break;
1242 }
1243
2/4
✓ Branch 0 taken 374 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 374 times.
✗ Branch 3 not taken.
374 coerced_keys->append_clone(res.to_dom());
1244
4/4
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 374 times.
✓ Branch 3 taken 3 times.
380 }
1245
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 3 times.
234 if (can_use_index) break;
1246
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 231 times.
283 }
1247
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 231 times.
257 if (!found) return;
1248 231 TABLE *table = found->table;
1249
2/4
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
231 Item_field *subs_item = new Item_field(found);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 if (!subs_item) return;
1251 auto res = make_unique_destroy_only<Json_wrapper>(thd->mem_root,
1252
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 coerced_keys.release());
1253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 if (res == nullptr) return;
1254 Item_json *array_arg =
1255
2/4
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
231 new (thd->mem_root) Item_json(std::move(res), (*func)->item_name);
1256
4/8
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 231 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 231 times.
231 if (!array_arg || array_arg->fix_fields(thd, nullptr)) return;
1257
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 table->mark_column_used(found, MARK_COLUMNS_READ);
1258
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 thd->change_item_tree(func, subs_item);
1259
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 thd->change_item_tree(vals, array_arg);
1260
3/4
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 231 times.
✓ Branch 3 taken 26 times.
257 }
1261
1262 /**
1263 Transformer function for GC substitution.
1264
1265 @param arg List of indexed GC field
1266
1267 @return this item on successful execution, nullptr on error
1268
1269 @details This function transforms a search condition. It doesn't change
1270 'this' item but rather changes its arguments. It takes list of GC fields
1271 and checks whether arguments of 'this' item matches them and index over
1272 the GC field isn't disabled with hints. If so, it replaces
1273 the argument with newly created Item_field which uses the matched GC field.
1274 The following predicates' arguments could be transformed:
1275 - EQ_FUNC, LT_FUNC, LE_FUNC, GE_FUNC, GT_FUNC, JSON_OVERLAPS
1276 - Left _or_ right argument if the opposite argument is a constant.
1277 - IN_FUNC, BETWEEN
1278 - Left argument if all other arguments are constant and of the same type.
1279 - MEMBER OF
1280 - Right argument if left argument is constant.
1281 - JSON_CONTAINS
1282 - First argument if the second argument is constant.
1283
1284 After transformation comparators are updated to take into account the new
1285 field.
1286
1287 Note: Range optimizer is used with multi-value indexes and it prefers
1288 constants. Outer references are not considered as constants in JSON functions.
1289 However, range optimizer supports dynamic ranges, where ranges are
1290 re-optimized for each row. But the range optimizer is currently not able to
1291 handle multi-valued indexes with dynamic ranges, hence we use only constants
1292 in these cases.
1293
1294 */
1295
1296 24173 Item *Item_func::gc_subst_transformer(uchar *arg) {
1297 24173 List<Field> *gc_fields = pointer_cast<List<Field> *>(arg);
1298
1299 307 auto is_const_or_outer_reference = [](const Item *item) {
1300 307 return ((item->used_tables() & ~(OUTER_REF_TABLE_BIT | INNER_TABLE_BIT)) ==
1301 307 0);
1302 };
1303
1304
7/8
✓ Branch 0 taken 24173 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23174 times.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 481 times.
✓ Branch 5 taken 164 times.
✓ Branch 6 taken 112 times.
✓ Branch 7 taken 160 times.
24173 switch (functype()) {
1305 23174 case EQ_FUNC:
1306 case LT_FUNC:
1307 case LE_FUNC:
1308 case GE_FUNC:
1309 case GT_FUNC: {
1310 23174 Item **func = nullptr;
1311 23174 Item *val = nullptr;
1312
1313 // Check if we can substitute a function with a GC. The
1314 // predicate must be on the form <expr> OP <constant> or
1315 // <constant> OP <expr>.
1316
5/6
✓ Branch 0 taken 23174 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 264 times.
✓ Branch 3 taken 22910 times.
✓ Branch 4 taken 264 times.
✓ Branch 5 taken 22910 times.
23438 if (args[0]->can_be_substituted_for_gc() &&
1317
2/4
✓ Branch 0 taken 264 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 264 times.
✗ Branch 3 not taken.
264 is_const_or_outer_reference(args[1])) {
1318 264 func = args;
1319 264 val = args[1];
1320
5/6
✓ Branch 0 taken 22910 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 22883 times.
✓ Branch 4 taken 15 times.
✓ Branch 5 taken 22895 times.
22937 } else if (args[1]->can_be_substituted_for_gc() &&
1321
3/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 12 times.
27 is_const_or_outer_reference(args[0])) {
1322 15 func = args + 1;
1323 15 val = args[0];
1324 } else {
1325 22895 break;
1326 }
1327
1328
3/6
✓ Branch 0 taken 279 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 279 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 279 times.
279 if (substitute_gc_expression(func, nullptr, gc_fields, val->result_type(),
1329 this))
1330 return nullptr; /* purecov: inspected */
1331 279 break;
1332 }
1333 82 case BETWEEN:
1334 case IN_FUNC: {
1335
3/4
✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 6 times.
82 if (!args[0]->can_be_substituted_for_gc()) break;
1336
1337 // Can only substitute if all the operands on the right-hand
1338 // side are constants of the same type.
1339
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 Item_result type = args[1]->result_type();
1340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!std::all_of(
1341
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 args + 1, args + arg_count,
1342 32 [type, is_const_or_outer_reference](const Item *item_arg) {
1343
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
32 return is_const_or_outer_reference(item_arg) &&
1344
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
32 item_arg->result_type() == type;
1345 })) {
1346 break;
1347 }
1348
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (substitute_gc_expression(args, nullptr, gc_fields, type, this))
1349 return nullptr;
1350 6 break;
1351 }
1352 481 case MEMBER_OF_FUNC: {
1353
1/2
✓ Branch 0 taken 481 times.
✗ Branch 1 not taken.
481 Item_result type = args[0]->result_type();
1354 /*
1355 Check whether MEMBER OF is applicable for optimization:
1356 1) 1st arg is constant for execution
1357 2) .. and it isn't NULL, as MEMBER OF can't be used to lookup NULLs
1358 3) 2nd arg can be substituted for a GC
1359 */
1360
1/2
✓ Branch 0 taken 481 times.
✗ Branch 1 not taken.
481 if (args[0]->const_for_execution() && // 1
1361
7/8
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 477 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 477 times.
✓ Branch 7 taken 4 times.
958 !args[0]->is_null() && // 2
1362
2/4
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
✗ Branch 3 not taken.
477 args[1]->can_be_substituted_for_gc(/*array=*/true)) { // 3
1363
2/4
✓ Branch 0 taken 477 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 477 times.
477 if (substitute_gc_expression(args + 1, args, gc_fields, type, this))
1364 return nullptr;
1365 }
1366 481 break;
1367 }
1368 164 case JSON_CONTAINS: {
1369 164 Json_wrapper vals_wr;
1370 164 String str;
1371 /*
1372 Check whether JSON_CONTAINS is applicable for optimization:
1373 1) 1st arg can be substituted with a generated column
1374 2) value to lookup is constant for execution
1375 3) value to lookup is a proper JSON doc
1376 4) value to lookup is an array or scalar
1377 */
1378
4/6
✓ Branch 0 taken 164 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 151 times.
328 if (!args[0]->can_be_substituted_for_gc(/*array=*/true) || // 1
1379
3/4
✓ Branch 0 taken 164 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 151 times.
164 !args[1]->const_for_execution()) // 2
1380 13 break;
1381
4/6
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 151 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 150 times.
151 if (get_json_wrapper(args, 1, &str, func_name(), &vals_wr)) { // 3
1382 1 return nullptr;
1383 }
1384
3/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 147 times.
300 if (args[1]->null_value ||
1385
3/4
✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 147 times.
150 vals_wr.type() == enum_json_type::J_OBJECT) // 4
1386 3 break;
1387
1/2
✓ Branch 0 taken 147 times.
✗ Branch 1 not taken.
147 gc_subst_overlaps_contains(args, args + 1, vals_wr, gc_fields);
1388 147 break;
1389
4/4
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 163 times.
✓ Branch 3 taken 1 times.
328 }
1390 112 case JSON_OVERLAPS: {
1391 112 Item **func = nullptr;
1392 112 int vals = -1;
1393
1394 /*
1395 Check whether JSON_OVERLAPS is applicable for optimization:
1396 1) One argument is constant for execution
1397 2) The other argument can be substituted with a generated column
1398 3) value to lookup is a proper JSON doc
1399 4) value to lookup is an array or scalar
1400 */
1401
5/6
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 91 times.
✓ Branch 5 taken 21 times.
216 if (args[0]->can_be_substituted_for_gc(/*array=*/true) && // 2
1402
3/4
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 13 times.
104 args[1]->const_for_execution()) { // 1
1403 91 func = args;
1404 91 vals = 1;
1405
3/6
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
42 } else if (args[1]->can_be_substituted_for_gc(/*array=*/true) && // 2
1406
2/4
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 args[0]->const_for_execution()) { // 1
1407 21 func = args + 1;
1408 21 vals = 0;
1409 } else {
1410 111 break;
1411 }
1412
1413 112 Json_wrapper vals_wr;
1414 112 String str;
1415
4/6
✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 111 times.
112 if (get_json_wrapper(args, vals, &str, func_name(), &vals_wr)) { // 3
1416 1 return nullptr;
1417 }
1418
3/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 110 times.
222 if (args[vals]->null_value ||
1419
3/4
✓ Branch 0 taken 111 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 110 times.
111 vals_wr.type() == enum_json_type::J_OBJECT) // 4
1420 1 break;
1421
1/2
✓ Branch 0 taken 110 times.
✗ Branch 1 not taken.
110 gc_subst_overlaps_contains(func, args + vals, vals_wr, gc_fields);
1422 110 break;
1423
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 111 times.
✓ Branch 2 taken 111 times.
✓ Branch 3 taken 1 times.
224 }
1424 160 default:
1425 160 break;
1426 }
1427 24171 return this;
1428 }
1429
1430 824 double Item_int_func::val_real() {
1431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 824 times.
824 assert(fixed == 1);
1432
1433
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 820 times.
824 return unsigned_flag ? (double)((ulonglong)val_int()) : (double)val_int();
1434 }
1435
1436 3004516 String *Item_int_func::val_str(String *str) {
1437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3004516 times.
3004516 assert(fixed == 1);
1438 3004516 longlong nr = val_int();
1439
2/2
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 3004160 times.
3004516 if (null_value) return nullptr;
1440 3004160 str->set_int(nr, unsigned_flag, collation.collation);
1441 3004160 return str;
1442 }
1443
1444 11247 bool Item_func_connection_id::itemize(Parse_context *pc, Item **res) {
1445
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11247 times.
11247 if (skip_itemize(res)) return false;
1446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11247 times.
11247 if (super::itemize(pc, res)) return true;
1447 11247 pc->thd->lex->safe_to_cache_query = false;
1448 11247 return false;
1449 }
1450
1451 2493 bool Item_func_connection_id::resolve_type(THD *thd) {
1452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2493 times.
2493 if (Item_int_func::resolve_type(thd)) return true;
1453 2493 unsigned_flag = true;
1454 2493 return false;
1455 }
1456
1457 2493 bool Item_func_connection_id::fix_fields(THD *thd, Item **ref) {
1458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2494 times.
2493 if (Item_int_func::fix_fields(thd, ref)) return true;
1459 2494 thd->thread_specific_used = true;
1460 2494 return false;
1461 }
1462
1463 6354 longlong Item_func_connection_id::val_int() {
1464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6354 times.
6354 assert(fixed);
1465 6354 return current_thd->variables.pseudo_thread_id;
1466 }
1467
1468 /**
1469 Check arguments to determine the data type for a numeric
1470 function of two arguments.
1471 */
1472
1473 3371036 void Item_num_op::set_numeric_type(void) {
1474
1/2
✓ Branch 0 taken 3371049 times.
✗ Branch 1 not taken.
3371036 DBUG_TRACE;
1475
3/10
✓ Branch 0 taken 3371051 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3371049 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3371049 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
3371049 DBUG_PRINT("info", ("name %s", func_name()));
1476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3371049 times.
3371049 assert(arg_count == 2);
1477
1/2
✓ Branch 0 taken 3371046 times.
✗ Branch 1 not taken.
3371049 Item_result r0 = args[0]->numeric_context_result_type();
1478
1/2
✓ Branch 0 taken 3371043 times.
✗ Branch 1 not taken.
3371046 Item_result r1 = args[1]->numeric_context_result_type();
1479
1480
2/4
✓ Branch 0 taken 3371045 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3371045 times.
✗ Branch 3 not taken.
3371043 assert(r0 != STRING_RESULT && r1 != STRING_RESULT);
1481
1482
4/4
✓ Branch 0 taken 3218446 times.
✓ Branch 1 taken 152599 times.
✓ Branch 2 taken 42971 times.
✓ Branch 3 taken 3175475 times.
3371045 if (r0 == REAL_RESULT || r1 == REAL_RESULT) {
1483 /*
1484 Since DATE/TIME/DATETIME data types return INT_RESULT/DECIMAL_RESULT
1485 type codes, we should never get to here when both fields are temporal.
1486 */
1487
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 195495 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
195570 assert(!args[0]->is_temporal() || !args[1]->is_temporal());
1488 195561 set_data_type(MYSQL_TYPE_DOUBLE);
1489 195561 hybrid_type = REAL_RESULT;
1490
1/2
✓ Branch 0 taken 195561 times.
✗ Branch 1 not taken.
195561 aggregate_float_properties(args, arg_count);
1491 195561 max_length = float_length(decimals);
1492
4/4
✓ Branch 0 taken 3048899 times.
✓ Branch 1 taken 126576 times.
✓ Branch 2 taken 17691 times.
✓ Branch 3 taken 3031208 times.
3175475 } else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT) {
1493 144267 set_data_type(MYSQL_TYPE_NEWDECIMAL);
1494 144268 hybrid_type = DECIMAL_RESULT;
1495
1/2
✓ Branch 0 taken 144268 times.
✗ Branch 1 not taken.
144268 result_precision();
1496 } else {
1497
2/4
✓ Branch 0 taken 3031214 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3031214 times.
✗ Branch 3 not taken.
3031208 assert(r0 == INT_RESULT && r1 == INT_RESULT);
1498 3031214 set_data_type(MYSQL_TYPE_LONGLONG);
1499 3031217 decimals = 0;
1500 3031217 hybrid_type = INT_RESULT;
1501
1/2
✓ Branch 0 taken 3031217 times.
✗ Branch 1 not taken.
3031217 result_precision();
1502 }
1503
3/14
✓ Branch 0 taken 3371044 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3371045 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3371045 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3371046 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
1504 ? "REAL_RESULT"
1505 : hybrid_type == DECIMAL_RESULT
1506 ? "DECIMAL_RESULT"
1507 : hybrid_type == INT_RESULT
1508 ? "INT_RESULT"
1509 : "--ILLEGAL!!!--")));
1510 3371045 }
1511
1512 /**
1513 Set data type for a numeric function with one argument
1514 (can be also used by a numeric function with many arguments, if the result
1515 type depends only on the first argument)
1516 */
1517
1518 146132 void Item_func_num1::set_numeric_type() {
1519
1/2
✓ Branch 0 taken 146133 times.
✗ Branch 1 not taken.
146132 DBUG_TRACE;
1520
3/10
✓ Branch 0 taken 146133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146133 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 146133 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
146133 DBUG_PRINT("info", ("name %s", func_name()));
1521
4/6
✓ Branch 0 taken 146132 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 142363 times.
✓ Branch 3 taken 1433 times.
✓ Branch 4 taken 2336 times.
✗ Branch 5 not taken.
146133 switch (hybrid_type = args[0]->result_type()) {
1522 142363 case INT_RESULT:
1523 142363 set_data_type(MYSQL_TYPE_LONGLONG);
1524 142364 unsigned_flag = args[0]->unsigned_flag;
1525 142364 break;
1526 1433 case STRING_RESULT:
1527 case REAL_RESULT:
1528 1433 set_data_type(MYSQL_TYPE_DOUBLE);
1529 1433 hybrid_type = REAL_RESULT;
1530 1433 max_length = float_length(decimals);
1531 1433 break;
1532 2336 case DECIMAL_RESULT:
1533 2336 set_data_type(MYSQL_TYPE_NEWDECIMAL);
1534 2336 unsigned_flag = args[0]->unsigned_flag;
1535 2336 break;
1536 default:
1537 assert(0);
1538 }
1539
3/14
✓ Branch 0 taken 146133 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 146133 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 146133 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
146133 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
1540 ? "REAL_RESULT"
1541 : hybrid_type == DECIMAL_RESULT
1542 ? "DECIMAL_RESULT"
1543 : hybrid_type == INT_RESULT
1544 ? "INT_RESULT"
1545 : "--ILLEGAL!!!--")));
1546 146133 }
1547
1548 2575 void Item_func_num1::fix_num_length_and_dec() {
1549 2575 decimals = args[0]->decimals;
1550 2575 max_length = args[0]->max_length;
1551 2575 }
1552
1553 /*
1554 Reject geometry arguments, should be called in resolve_type() for
1555 SQL functions/operators where geometries are not suitable as operands.
1556 */
1557 7645009 bool reject_geometry_args(uint arg_count, Item **args, Item_result_field *me) {
1558 /*
1559 We want to make sure the operands are not GEOMETRY strings because
1560 it's meaningless for them to participate in arithmetic and/or numerical
1561 calculations.
1562
1563 When a variable holds a MySQL Geometry byte string, it is regarded as a
1564 string rather than a MYSQL_TYPE_GEOMETRY, so here we can't catch an illegal
1565 variable argument which was assigned with a geometry.
1566
1567 Item::data_type() requires the item not be of ROW_RESULT, since a row
1568 isn't a field.
1569 */
1570
2/2
✓ Branch 0 taken 13068476 times.
✓ Branch 1 taken 7644920 times.
20713396 for (uint i = 0; i < arg_count; i++) {
1571
6/6
✓ Branch 0 taken 13068363 times.
✓ Branch 1 taken 118 times.
✓ Branch 2 taken 97 times.
✓ Branch 3 taken 13068269 times.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 13068387 times.
26136842 if (args[i]->result_type() != ROW_RESULT &&
1572 13068363 args[i]->data_type() == MYSQL_TYPE_GEOMETRY) {
1573 97 my_error(ER_WRONG_ARGUMENTS, MYF(0), me->func_name());
1574 97 return true;
1575 }
1576 }
1577
1578 7644920 return false;
1579 }
1580
1581 /**
1582 Go through the arguments of a function and check if any of them are
1583 JSON. If a JSON argument is found, raise a warning saying that this
1584 operation is not supported yet. This function is used to notify
1585 users that they are comparing JSON values using a mechanism that has
1586 not yet been updated to use the JSON comparator. JSON values are
1587 typically handled as strings in that case.
1588
1589 @param arg_count the number of arguments
1590 @param args the arguments to go through looking for JSON values
1591 @param msg the message that explains what is not supported
1592 */
1593 20752 void unsupported_json_comparison(size_t arg_count, Item **args,
1594 const char *msg) {
1595
2/2
✓ Branch 0 taken 59185 times.
✓ Branch 1 taken 20749 times.
79934 for (size_t i = 0; i < arg_count; ++i) {
1596
6/6
✓ Branch 0 taken 4078 times.
✓ Branch 1 taken 55107 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4075 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 59182 times.
63263 if (args[i]->result_type() == STRING_RESULT &&
1597 4078 args[i]->data_type() == MYSQL_TYPE_JSON) {
1598 3 push_warning_printf(current_thd, Sql_condition::SL_WARNING,
1599 ER_NOT_SUPPORTED_YET,
1600 3 ER_THD(current_thd, ER_NOT_SUPPORTED_YET), msg);
1601 3 break;
1602 }
1603 }
1604 20752 }
1605
1606 4478449 bool Item_func_numhybrid::resolve_type(THD *thd) {
1607
3/4
✓ Branch 0 taken 4220671 times.
✓ Branch 1 taken 257778 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4220671 times.
4478449 assert(arg_count == 1 || arg_count == 2);
1608 /*
1609 If no arguments have type information, return and trust
1610 propagate_type() to assign data types later.
1611 If some argument has type information, propagate the same type to
1612 the other argument.
1613 */
1614
2/2
✓ Branch 0 taken 257778 times.
✓ Branch 1 taken 4220671 times.
4478449 if (arg_count == 1) {
1615
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 257767 times.
257778 if (args[0]->data_type() == MYSQL_TYPE_INVALID) return false;
1616 } else {
1617
6/6
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 4220621 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 4220654 times.
4220722 if (args[0]->data_type() == MYSQL_TYPE_INVALID &&
1618 51 args[1]->data_type() == MYSQL_TYPE_INVALID)
1619 18 return false;
1620
1621
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 4220623 times.
4220654 if (args[0]->data_type() == MYSQL_TYPE_INVALID) {
1622
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
33 if (args[0]->propagate_type(thd, Type_properties(*args[1]))) return true;
1623
2/2
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 4220356 times.
4220623 } else if (args[1]->data_type() == MYSQL_TYPE_INVALID) {
1624
2/4
✓ Branch 0 taken 267 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 267 times.
267 if (args[1]->propagate_type(thd, Type_properties(*args[0]))) return true;
1625 }
1626 }
1627
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4478424 times.
4478423 if (resolve_type_inner(thd)) return true;
1628 4478424 return reject_geometry_args(arg_count, args, this);
1629 }
1630
1631 4366800 bool Item_func_numhybrid::resolve_type_inner(THD *) {
1632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4366807 times.
4366800 assert(args[0]->data_type() != MYSQL_TYPE_INVALID);
1633
3/4
✓ Branch 0 taken 4220677 times.
✓ Branch 1 taken 146130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4220678 times.
4366807 assert(arg_count == 1 || args[1]->data_type() != MYSQL_TYPE_INVALID);
1634 4366808 fix_num_length_and_dec();
1635 4366797 set_numeric_type();
1636 4366811 return false;
1637 }
1638
1639 8725500 String *Item_func_numhybrid::val_str(String *str) {
1640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8725500 times.
8725500 assert(fixed == 1);
1641
4/5
✓ Branch 0 taken 30412 times.
✓ Branch 1 taken 199874 times.
✓ Branch 2 taken 17479 times.
✓ Branch 3 taken 8477735 times.
✗ Branch 4 not taken.
8725500 switch (hybrid_type) {
1642 30412 case DECIMAL_RESULT: {
1643 30412 my_decimal decimal_value, *val;
1644
3/4
✓ Branch 0 taken 30412 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5254 times.
✓ Branch 3 taken 25158 times.
30412 if (!(val = decimal_op(&decimal_value))) return nullptr; // null is set
1645
1/2
✓ Branch 0 taken 25158 times.
✗ Branch 1 not taken.
25158 my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, false, val);
1646 25158 str->set_charset(collation.collation);
1647
1/2
✓ Branch 0 taken 25158 times.
✗ Branch 1 not taken.
25158 my_decimal2string(E_DEC_FATAL_ERROR, val, str);
1648 25158 break;
1649
2/2
✓ Branch 0 taken 5254 times.
✓ Branch 1 taken 25158 times.
30412 }
1650 199874 case INT_RESULT: {
1651 199874 longlong nr = int_op();
1652
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 199834 times.
199874 if (null_value) return nullptr; /* purecov: inspected */
1653 199834 str->set_int(nr, unsigned_flag, collation.collation);
1654 199834 break;
1655 }
1656 17479 case REAL_RESULT: {
1657 17479 double nr = real_op();
1658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17479 times.
17479 if (null_value) return nullptr; /* purecov: inspected */
1659 17479 str->set_real(nr, decimals, collation.collation);
1660 17479 break;
1661 }
1662 8477735 case STRING_RESULT:
1663
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 8477669 times.
8477735 switch (data_type()) {
1664 45 case MYSQL_TYPE_DATETIME:
1665 case MYSQL_TYPE_TIMESTAMP:
1666 45 return val_string_from_datetime(str);
1667 16 case MYSQL_TYPE_DATE:
1668 16 return val_string_from_date(str);
1669 5 case MYSQL_TYPE_TIME:
1670 5 return val_string_from_time(str);
1671 8477669 default:
1672 8477669 break;
1673 }
1674 8477669 return str_op(&str_value);
1675 default:
1676 assert(0);
1677 }
1678 242471 return str;
1679 }
1680
1681 3645173 double Item_func_numhybrid::val_real() {
1682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3645173 times.
3645173 assert(fixed == 1);
1683
4/5
✓ Branch 0 taken 329486 times.
✓ Branch 1 taken 212345 times.
✓ Branch 2 taken 3103329 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
3645173 switch (hybrid_type) {
1684 329486 case DECIMAL_RESULT: {
1685 329486 my_decimal decimal_value, *val;
1686 double result;
1687
3/4
✓ Branch 0 taken 329486 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 329402 times.
329486 if (!(val = decimal_op(&decimal_value))) return 0.0; // null is set
1688
1/2
✓ Branch 0 taken 329402 times.
✗ Branch 1 not taken.
329402 my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
1689 329402 return result;
1690 329486 }
1691 212345 case INT_RESULT: {
1692 212345 longlong result = int_op();
1693
2/2
✓ Branch 0 taken 2285 times.
✓ Branch 1 taken 210060 times.
212345 return unsigned_flag ? (double)((ulonglong)result) : (double)result;
1694 }
1695 3103329 case REAL_RESULT:
1696 3103329 return real_op();
1697 18 case STRING_RESULT: {
1698
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
18 switch (data_type()) {
1699 4 case MYSQL_TYPE_TIME:
1700 case MYSQL_TYPE_DATE:
1701 case MYSQL_TYPE_DATETIME:
1702 case MYSQL_TYPE_TIMESTAMP:
1703
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 return val_real_from_decimal();
1704 14 default:
1705 14 break;
1706 }
1707 const char *end_not_used;
1708 int err_not_used;
1709
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 String *res = str_op(&str_value);
1710
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
14 return (res ? my_strntod(res->charset(), res->ptr(), res->length(),
1711 &end_not_used, &err_not_used)
1712 14 : 0.0);
1713 }
1714 default:
1715 assert(0);
1716 }
1717 return 0.0;
1718 }
1719
1720 127776206 longlong Item_func_numhybrid::val_int() {
1721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 127776206 times.
127776206 assert(fixed == 1);
1722
4/5
✓ Branch 0 taken 1154228 times.
✓ Branch 1 taken 126032566 times.
✓ Branch 2 taken 589711 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
127776206 switch (hybrid_type) {
1723 1154228 case DECIMAL_RESULT: {
1724 1154228 my_decimal decimal_value, *val;
1725
3/4
✓ Branch 0 taken 1154228 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 1154218 times.
1154228 if (!(val = decimal_op(&decimal_value))) return 0; // null is set
1726 longlong result;
1727
1/2
✓ Branch 0 taken 1154218 times.
✗ Branch 1 not taken.
1154218 my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
1728 1154218 return result;
1729 1154228 }
1730 126032566 case INT_RESULT:
1731 126032566 return int_op();
1732 589711 case REAL_RESULT: {
1733 589711 return llrint_with_overflow_check(real_op());
1734 }
1735 5 case STRING_RESULT: {
1736
4/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
5 switch (data_type()) {
1737 1 case MYSQL_TYPE_DATE:
1738
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return val_int_from_date();
1739 2 case MYSQL_TYPE_DATETIME:
1740 case MYSQL_TYPE_TIMESTAMP:
1741
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return val_int_from_datetime();
1742 1 case MYSQL_TYPE_TIME:
1743
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return val_int_from_time();
1744 1 default:
1745 1 break;
1746 }
1747 int err_not_used;
1748 String *res;
1749
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!(res = str_op(&str_value))) return 0;
1750
1751 1 const char *end = res->ptr() + res->length();
1752 1 const CHARSET_INFO *cs = res->charset();
1753
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
1754 }
1755 default:
1756 assert(0);
1757 }
1758 return 0;
1759 }
1760
1761 2583942 my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) {
1762 2583942 my_decimal *val = decimal_value;
1763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2583942 times.
2583942 assert(fixed == 1);
1764
4/5
✓ Branch 0 taken 2076323 times.
✓ Branch 1 taken 507482 times.
✓ Branch 2 taken 113 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
2583942 switch (hybrid_type) {
1765 2076323 case DECIMAL_RESULT:
1766 2076323 val = decimal_op(decimal_value);
1767 2076323 break;
1768 507482 case INT_RESULT: {
1769 507482 longlong result = int_op();
1770 507482 int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
1771 507482 break;
1772 }
1773 113 case REAL_RESULT: {
1774 113 double result = real_op();
1775 113 double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
1776 113 break;
1777 }
1778 24 case STRING_RESULT: {
1779
3/3
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 14 times.
24 switch (data_type()) {
1780 9 case MYSQL_TYPE_DATE:
1781 case MYSQL_TYPE_DATETIME:
1782 case MYSQL_TYPE_TIMESTAMP:
1783 9 return val_decimal_from_date(decimal_value);
1784 1 case MYSQL_TYPE_TIME:
1785 1 return val_decimal_from_time(decimal_value);
1786 14 default:
1787 14 break;
1788 }
1789 String *res;
1790
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 3 times.
14 if (!(res = str_op(&str_value))) return nullptr;
1791
1792 3 str2my_decimal(E_DEC_FATAL_ERROR, res->ptr(), res->length(),
1793 res->charset(), decimal_value);
1794 3 break;
1795 }
1796 case ROW_RESULT:
1797 default:
1798 assert(0);
1799 }
1800 2583921 return val;
1801 }
1802
1803 224 bool Item_func_numhybrid::get_date(MYSQL_TIME *ltime,
1804 my_time_flags_t fuzzydate) {
1805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
224 assert(fixed == 1);
1806
4/4
✓ Branch 0 taken 182 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 37 times.
224 switch (data_type()) {
1807 182 case MYSQL_TYPE_DATE:
1808 case MYSQL_TYPE_DATETIME:
1809 case MYSQL_TYPE_TIMESTAMP:
1810 182 return date_op(ltime, fuzzydate);
1811 4 case MYSQL_TYPE_TIME:
1812 4 return get_date_from_time(ltime);
1813 1 case MYSQL_TYPE_YEAR:
1814 1 return get_date_from_int(ltime, fuzzydate);
1815 37 default:
1816 37 return Item::get_date_from_non_temporal(ltime, fuzzydate);
1817 }
1818 }
1819
1820 44 bool Item_func_numhybrid::get_time(MYSQL_TIME *ltime) {
1821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 assert(fixed == 1);
1822
5/5
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 5 times.
44 switch (data_type()) {
1823 20 case MYSQL_TYPE_TIME:
1824 20 return time_op(ltime);
1825 2 case MYSQL_TYPE_DATE:
1826 2 return get_time_from_date(ltime);
1827 16 case MYSQL_TYPE_DATETIME:
1828 case MYSQL_TYPE_TIMESTAMP:
1829 16 return get_time_from_datetime(ltime);
1830 1 case MYSQL_TYPE_YEAR:
1831 1 return get_time_from_int(ltime);
1832 5 default:
1833 5 return Item::get_time_from_non_temporal(ltime);
1834 }
1835 }
1836
1837 126 void Item_typecast_signed::print(const THD *thd, String *str,
1838 enum_query_type query_type) const {
1839 126 str->append(STRING_WITH_LEN("cast("));
1840 126 args[0]->print(thd, str, query_type);
1841 126 str->append(STRING_WITH_LEN(" as signed)"));
1842 126 }
1843
1844 4092 bool Item_typecast_signed::resolve_type(THD *thd) {
1845
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4091 times.
4092 if (reject_geometry_args(arg_count, args, this)) return true;
1846 4091 return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true);
1847 }
1848
1849 25819 static longlong val_int_from_str(Item *item, bool unsigned_flag,
1850 bool *null_value) {
1851 /*
1852 For a string result, we must first get the string and then convert it
1853 to a longlong
1854 */
1855 25819 StringBuffer<MAX_FIELD_WIDTH> tmp;
1856
1/2
✓ Branch 0 taken 25819 times.
✗ Branch 1 not taken.
25819 const String *res = item->val_str(&tmp);
1857 25819 *null_value = item->null_value;
1858
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 25717 times.
25819 if (*null_value) return 0;
1859
1860 25717 size_t length = res->length();
1861 25717 const char *start = res->ptr();
1862 25717 const char *end = start + length;
1863
1/2
✓ Branch 0 taken 25717 times.
✗ Branch 1 not taken.
25717 return longlong_from_string_with_check(res->charset(), start, end,
1864 25717 unsigned_flag);
1865 25819 }
1866
1867 26040 longlong Item_typecast_signed::val_int() {
1868 longlong value;
1869
1870
6/6
✓ Branch 0 taken 25724 times.
✓ Branch 1 taken 316 times.
✓ Branch 2 taken 174 times.
✓ Branch 3 taken 25550 times.
✓ Branch 4 taken 490 times.
✓ Branch 5 taken 25550 times.
26040 if (args[0]->cast_to_int_type() != STRING_RESULT || args[0]->is_temporal()) {
1871 490 value = args[0]->val_int();
1872 490 null_value = args[0]->null_value;
1873 } else {
1874 25550 value = val_int_from_str(args[0], unsigned_flag, &null_value);
1875 }
1876
1877 #ifndef NDEBUG
1878
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 25951 times.
26040 if (null_value) {
1879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 assert(is_nullable());
1880
2/2
✓ Branch 0 taken 25799 times.
✓ Branch 1 taken 152 times.
25951 } else if (value >= 0) {
1881 25799 const int digits = count_digits(static_cast<ulonglong>(value));
1882
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25799 times.
25799 assert(digits <= decimal_int_part());
1883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25799 times.
25799 assert(static_cast<unsigned>(digits) <= max_length);
1884 } else {
1885 const int digits =
1886 152 count_digits(ulonglong{0} - static_cast<ulonglong>(value));
1887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 assert(digits <= decimal_int_part());
1888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
152 assert(static_cast<unsigned>(digits) + 1 <= max_length);
1889 }
1890 #endif
1891
1892 26040 return value;
1893 }
1894
1895 16390 void Item_typecast_unsigned::print(const THD *thd, String *str,
1896 enum_query_type query_type) const {
1897 16390 str->append(STRING_WITH_LEN("cast("));
1898 16390 args[0]->print(thd, str, query_type);
1899 16390 str->append(STRING_WITH_LEN(" as unsigned)"));
1900 16390 }
1901
1902 1107932 bool Item_typecast_unsigned::resolve_type(THD *thd) {
1903
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1107931 times.
1107932 if (reject_geometry_args(arg_count, args, this)) return true;
1904 1107931 return args[0]->propagate_type(thd, MYSQL_TYPE_LONGLONG, false, true);
1905 }
1906
1907 3796777 longlong Item_typecast_unsigned::val_int() {
1908 3796777 longlong value = 0;
1909
1910
3/4
✓ Branch 0 taken 3796777 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 518 times.
✓ Branch 3 taken 3796259 times.
3796777 if (args[0]->cast_to_int_type() == DECIMAL_RESULT) {
1911
1/2
✓ Branch 0 taken 518 times.
✗ Branch 1 not taken.
518 my_decimal tmp, *dec = args[0]->val_decimal(&tmp);
1912 518 null_value = args[0]->null_value;
1913
2/2
✓ Branch 0 taken 511 times.
✓ Branch 1 taken 7 times.
518 if (!null_value) {
1914
1/2
✓ Branch 0 taken 511 times.
✗ Branch 1 not taken.
511 my_decimal2int(E_DEC_FATAL_ERROR, dec, !dec->sign(), &value);
1915 }
1916
7/8
✓ Branch 0 taken 3796259 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 692333 times.
✓ Branch 3 taken 3103926 times.
✓ Branch 4 taken 692064 times.
✓ Branch 5 taken 269 times.
✓ Branch 6 taken 3795990 times.
✓ Branch 7 taken 269 times.
4489110 } else if (args[0]->cast_to_int_type() != STRING_RESULT ||
1917 692333 args[0]->is_temporal()) {
1918
1/2
✓ Branch 0 taken 3795990 times.
✗ Branch 1 not taken.
3795990 value = args[0]->val_int();
1919 3795990 null_value = args[0]->null_value;
1920 } else {
1921
1/2
✓ Branch 0 taken 269 times.
✗ Branch 1 not taken.
269 value = val_int_from_str(args[0], unsigned_flag, &null_value);
1922 }
1923
1924
3/4
✓ Branch 0 taken 593184 times.
✓ Branch 1 taken 3203593 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593184 times.
3796777 assert(!null_value || is_nullable());
1925
3/6
✓ Branch 0 taken 3796777 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3796777 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3796777 times.
3796777 assert(count_digits(static_cast<ulonglong>(value)) <= decimal_int_part());
1926
1927 3796777 return value;
1928 }
1929
1930 489 String *Item_typecast_decimal::val_str(String *str) {
1931
1/2
✓ Branch 0 taken 489 times.
✗ Branch 1 not taken.
489 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1932
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 427 times.
489 if (null_value) return nullptr;
1933
1/2
✓ Branch 0 taken 427 times.
✗ Branch 1 not taken.
427 my_decimal2string(E_DEC_FATAL_ERROR, tmp, str);
1934 427 return str;
1935 489 }
1936
1937 6 double Item_typecast_decimal::val_real() {
1938
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1939 double res;
1940
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (null_value) return 0.0;
1941
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
1942 4 return res;
1943 6 }
1944
1945 14 longlong Item_typecast_decimal::val_int() {
1946
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 my_decimal tmp_buf, *tmp = val_decimal(&tmp_buf);
1947 longlong res;
1948
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (null_value) return 0;
1949
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
1950 12 return res;
1951 14 }
1952
1953 11229 my_decimal *Item_typecast_decimal::val_decimal(my_decimal *dec) {
1954
1/2
✓ Branch 0 taken 11229 times.
✗ Branch 1 not taken.
11229 my_decimal tmp_buf, *tmp = args[0]->val_decimal(&tmp_buf);
1955 bool sign;
1956 uint precision;
1957
1958
2/2
✓ Branch 0 taken 265 times.
✓ Branch 1 taken 10964 times.
11229 if ((null_value = args[0]->null_value)) return nullptr;
1959
1/2
✓ Branch 0 taken 10964 times.
✗ Branch 1 not taken.
10964 my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, false, dec);
1960 10964 sign = dec->sign();
1961
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10964 times.
10964 if (unsigned_flag) {
1962 if (sign) {
1963 my_decimal_set_zero(dec);
1964 goto err;
1965 }
1966 }
1967 precision =
1968 10964 my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
1969
3/4
✓ Branch 0 taken 10964 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 10931 times.
10964 if (precision - decimals < (uint)my_decimal_intg(dec)) {
1970
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 max_my_decimal(dec, precision, decimals);
1971 33 dec->sign(sign);
1972 33 goto err;
1973 }
1974 10931 return dec;
1975
1976 33 err:
1977 33 push_warning_printf(
1978
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 current_thd, Sql_condition::SL_WARNING, ER_WARN_DATA_OUT_OF_RANGE,
1979
2/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
33 ER_THD(current_thd, ER_WARN_DATA_OUT_OF_RANGE), item_name.ptr(), 1L);
1980 33 return dec;
1981 11229 }
1982
1983 113 void Item_typecast_decimal::print(const THD *thd, String *str,
1984 enum_query_type query_type) const {
1985 uint precision =
1986 113 my_decimal_length_to_precision(max_length, decimals, unsigned_flag);
1987 113 str->append(STRING_WITH_LEN("cast("));
1988 113 args[0]->print(thd, str, query_type);
1989 113 str->append(STRING_WITH_LEN(" as decimal("));
1990 113 str->append_ulonglong(precision);
1991 113 str->append(',');
1992 113 str->append_ulonglong(decimals);
1993 113 str->append(')');
1994 113 str->append(')');
1995 113 }
1996
1997 1 String *Item_typecast_real::val_str(String *str) {
1998 1 double res = val_real();
1999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (null_value) return nullptr;
2000
2001 1 str->set_real(res, decimals, collation.collation);
2002 1 return str;
2003 }
2004
2005 23460 double Item_typecast_real::val_real() {
2006 23460 double res = args[0]->val_real();
2007 23460 null_value = args[0]->null_value;
2008
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 23438 times.
23460 if (null_value) return 0.0;
2009
4/4
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 23203 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 23436 times.
23673 if (data_type() == MYSQL_TYPE_FLOAT &&
2010
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 1 times.
235 ((res > std::numeric_limits<float>::max()) ||
2011
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 233 times.
234 res < std::numeric_limits<float>::lowest()))
2012 2 return raise_float_overflow();
2013 23436 return check_float_overflow(res);
2014 }
2015
2016 1 longlong Item_func::val_int_from_real() {
2017 1 double res = val_real();
2018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (null_value) return 0;
2019
2020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (unsigned_flag) {
2021 if (res < 0 || res >= ULLONG_MAX_DOUBLE) {
2022 return raise_integer_overflow();
2023 } else
2024 return (longlong)double2ulonglong(res);
2025 } else {
2026
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (res <= LLONG_MIN || res > LLONG_MAX_DOUBLE) {
2027 1 return raise_integer_overflow();
2028 } else
2029 return (longlong)res;
2030 }
2031 }
2032
2033 1 bool Item_typecast_real::get_date(MYSQL_TIME *ltime,
2034 my_time_flags_t fuzzydate) {
2035 1 return my_double_to_datetime_with_warn(val_real(), ltime, fuzzydate);
2036 }
2037
2038 1 bool Item_typecast_real::get_time(MYSQL_TIME *ltime) {
2039 1 return my_double_to_time_with_warn(val_real(), ltime);
2040 }
2041
2042 2 my_decimal *Item_typecast_real::val_decimal(my_decimal *decimal_value) {
2043 2 double result = val_real();
2044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (null_value) return nullptr;
2045 2 double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
2046
2047 2 return decimal_value;
2048 }
2049
2050 399 void Item_typecast_real::print(const THD *thd, String *str,
2051 enum_query_type query_type) const {
2052 399 str->append(STRING_WITH_LEN("cast("));
2053 399 args[0]->print(thd, str, query_type);
2054 399 str->append(STRING_WITH_LEN(" as "));
2055
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 393 times.
✓ Branch 2 taken 399 times.
✗ Branch 3 not taken.
399 str->append((data_type() == MYSQL_TYPE_FLOAT) ? "float)" : "double)");
2056 399 }
2057
2058 1254897 double Item_func_plus::real_op() {
2059 1254897 double val1 = args[0]->val_real();
2060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1254900 times.
1254900 if (current_thd->is_error()) return error_real();
2061 1254900 double val2 = args[1]->val_real();
2062
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1254896 times.
1254899 if (current_thd->is_error()) return error_real();
2063
2064
6/6
✓ Branch 0 taken 1254864 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 1254834 times.
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 1254834 times.
1254896 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2065 1254834 double value = val1 + val2;
2066 1254834 return check_float_overflow(value);
2067 }
2068
2069 117541738 longlong Item_func_plus::int_op() {
2070 117541738 longlong val0 = args[0]->val_int();
2071
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 117542134 times.
117542071 if (current_thd->is_error()) return error_int();
2072 117542134 longlong val1 = args[1]->val_int();
2073
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 117542127 times.
117541914 if (current_thd->is_error()) return error_int();
2074 117542127 longlong res = static_cast<unsigned long long>(val0) +
2075 117542127 static_cast<unsigned long long>(val1);
2076 117542127 bool res_unsigned = false;
2077
2078
6/6
✓ Branch 0 taken 117535064 times.
✓ Branch 1 taken 7063 times.
✓ Branch 2 taken 544 times.
✓ Branch 3 taken 117534520 times.
✓ Branch 4 taken 7607 times.
✓ Branch 5 taken 117534520 times.
117542127 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2079
2080 /*
2081 First check whether the result can be represented as a
2082 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2083 with this Item's unsigned_flag by calling check_integer_overflow().
2084 */
2085
2/2
✓ Branch 0 taken 466793 times.
✓ Branch 1 taken 117067727 times.
117534520 if (args[0]->unsigned_flag) {
2086
4/4
✓ Branch 0 taken 100550 times.
✓ Branch 1 taken 366243 times.
✓ Branch 2 taken 100549 times.
✓ Branch 3 taken 1 times.
466793 if (args[1]->unsigned_flag || val1 >= 0) {
2087
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 466765 times.
466792 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)val1)) goto err;
2088 466765 res_unsigned = true;
2089 } else {
2090 /* val1 is negative */
2091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((ulonglong)val0 > (ulonglong)LLONG_MAX) res_unsigned = true;
2092 }
2093 } else {
2094
2/2
✓ Branch 0 taken 25315 times.
✓ Branch 1 taken 117042412 times.
117067727 if (args[1]->unsigned_flag) {
2095
2/2
✓ Branch 0 taken 25313 times.
✓ Branch 1 taken 2 times.
25315 if (val0 >= 0) {
2096
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 25312 times.
25313 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)val1))
2097 1 goto err;
2098 25312 res_unsigned = true;
2099 } else {
2100
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if ((ulonglong)val1 > (ulonglong)LLONG_MAX) res_unsigned = true;
2101 }
2102 } else {
2103
4/4
✓ Branch 0 taken 117037774 times.
✓ Branch 1 taken 4638 times.
✓ Branch 2 taken 117032207 times.
✓ Branch 3 taken 5567 times.
117042412 if (val0 >= 0 && val1 >= 0)
2104 117032207 res_unsigned = true;
2105
6/6
✓ Branch 0 taken 4347 times.
✓ Branch 1 taken 5858 times.
✓ Branch 2 taken 1683 times.
✓ Branch 3 taken 2664 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1682 times.
10205 else if (val0 < 0 && val1 < 0 && res >= 0)
2106 1 goto err;
2107 }
2108 }
2109 117534491 return check_integer_overflow(res, res_unsigned);
2110
2111 29 err:
2112 29 return raise_integer_overflow();
2113 }
2114
2115 /**
2116 Calculate plus of two decimals.
2117
2118 @param decimal_value Buffer that can be used to store result
2119
2120 @return Value of operation as a decimal
2121 @retval
2122 0 Value was NULL; In this case null_value is set
2123 */
2124
2125 225500 my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) {
2126 225500 my_decimal value1, *val1;
2127 225500 my_decimal value2, *val2;
2128
1/2
✓ Branch 0 taken 225500 times.
✗ Branch 1 not taken.
225500 val1 = args[0]->val_decimal(&value1);
2129
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 225492 times.
225500 if ((null_value = args[0]->null_value)) return nullptr;
2130
1/2
✓ Branch 0 taken 225492 times.
✗ Branch 1 not taken.
225492 val2 = args[1]->val_decimal(&value2);
2131
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 225471 times.
225492 if ((null_value = args[1]->null_value)) return nullptr;
2132
2133
2/4
✓ Branch 0 taken 225471 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 225471 times.
✗ Branch 3 not taken.
225471 if (check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 225471 times.
225471 decimal_value, val1, val2)) > 3) {
2135 return error_decimal(decimal_value);
2136 }
2137 225471 return decimal_value;
2138 225500 }
2139
2140 /**
2141 Set precision of results for additive operations (+ and -)
2142 */
2143 2252788 void Item_func_additive_op::result_precision() {
2144 2252788 decimals = max(args[0]->decimals, args[1]->decimals);
2145
1/2
✓ Branch 0 taken 2252790 times.
✗ Branch 1 not taken.
2252791 int arg1_int = args[0]->decimal_precision() - args[0]->decimals;
2146
1/2
✓ Branch 0 taken 2252791 times.
✗ Branch 1 not taken.
2252790 int arg2_int = args[1]->decimal_precision() - args[1]->decimals;
2147 2252791 int precision = max(arg1_int, arg2_int) + 1 + decimals;
2148
2149 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2150
3/4
✓ Branch 0 taken 2252793 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2213777 times.
✓ Branch 3 taken 39016 times.
2252792 if (result_type() == INT_RESULT)
2151 2213777 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2152 else
2153 39016 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2154 4505594 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2155 2252793 unsigned_flag);
2156 2252801 }
2157
2158 /**
2159 The following function is here to allow the user to force
2160 subtraction of UNSIGNED BIGINT/DECIMAL to return negative values.
2161 */
2162
2163 943576 bool Item_func_minus::resolve_type(THD *thd) {
2164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 943574 times.
943576 if (Item_num_op::resolve_type(thd)) return true;
2165
4/4
✓ Branch 0 taken 28100 times.
✓ Branch 1 taken 915474 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 28071 times.
943574 if (unsigned_flag && (thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
2166 29 unsigned_flag = false;
2167 943574 return false;
2168 }
2169
2170 5045 double Item_func_minus::real_op() {
2171 5045 double val1 = args[0]->val_real();
2172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5045 times.
5045 if (current_thd->is_error()) return error_real();
2173 5045 double val2 = args[1]->val_real();
2174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5045 times.
5045 if (current_thd->is_error()) return error_real();
2175
2176
6/6
✓ Branch 0 taken 5044 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5043 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 5043 times.
5045 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2177 5043 double value = val1 - val2;
2178 5043 return check_float_overflow(value);
2179 }
2180
2181 2520878 longlong Item_func_minus::int_op() {
2182 2520878 longlong val0 = args[0]->val_int();
2183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2520878 times.
2520878 if (current_thd->is_error()) return error_int();
2184 2520878 longlong val1 = args[1]->val_int();
2185
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2520876 times.
2520878 if (current_thd->is_error()) return error_int();
2186 2520876 longlong res = static_cast<unsigned long long>(val0) -
2187 2520876 static_cast<unsigned long long>(val1);
2188 2520876 bool res_unsigned = false;
2189
2190
6/6
✓ Branch 0 taken 2520819 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2520810 times.
✓ Branch 4 taken 66 times.
✓ Branch 5 taken 2520810 times.
2520876 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2191
2192 /*
2193 First check whether the result can be represented as a
2194 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2195 with this Item's unsigned_flag by calling check_integer_overflow().
2196 */
2197
2/2
✓ Branch 0 taken 630602 times.
✓ Branch 1 taken 1890208 times.
2520810 if (args[0]->unsigned_flag) {
2198
2/2
✓ Branch 0 taken 1285 times.
✓ Branch 1 taken 629317 times.
630602 if (args[1]->unsigned_flag) {
2199
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1281 times.
1285 if ((ulonglong)val0 < (ulonglong)val1) {
2200
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (res >= 0) goto err;
2201 } else
2202 1281 res_unsigned = true;
2203 } else {
2204
2/2
✓ Branch 0 taken 629315 times.
✓ Branch 1 taken 2 times.
629317 if (val1 >= 0) {
2205
2/2
✓ Branch 0 taken 609146 times.
✓ Branch 1 taken 20169 times.
629315 if ((ulonglong)val0 > (ulonglong)val1) res_unsigned = true;
2206 } else {
2207
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (test_if_sum_overflows_ull((ulonglong)val0, (ulonglong)-val1))
2208 1 goto err;
2209 1 res_unsigned = true;
2210 }
2211 }
2212 } else {
2213
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1890170 times.
1890208 if (args[1]->unsigned_flag) {
2214
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 37 times.
38 if ((ulonglong)(val0 - LLONG_MIN) < (ulonglong)val1) goto err;
2215 } else {
2216
4/4
✓ Branch 0 taken 1884912 times.
✓ Branch 1 taken 5258 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 1884875 times.
1890170 if (val0 >= 0 && val1 < 0)
2217 37 res_unsigned = true;
2218
5/6
✓ Branch 0 taken 5258 times.
✓ Branch 1 taken 1884875 times.
✓ Branch 2 taken 5258 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5257 times.
1890133 else if (val0 < 0 && val1 > 0 && res >= 0)
2219 1 goto err;
2220 }
2221 }
2222 2520806 return check_integer_overflow(res, res_unsigned);
2223
2224 4 err:
2225 4 return raise_integer_overflow();
2226 }
2227
2228 /**
2229 See Item_func_plus::decimal_op for comments.
2230 */
2231
2232 203942 my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value) {
2233 203942 my_decimal value1, *val1;
2234 203942 my_decimal value2, *val2;
2235
2236
1/2
✓ Branch 0 taken 203942 times.
✗ Branch 1 not taken.
203942 val1 = args[0]->val_decimal(&value1);
2237
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 203784 times.
203942 if ((null_value = args[0]->null_value)) return nullptr;
2238
2239
1/2
✓ Branch 0 taken 203784 times.
✗ Branch 1 not taken.
203784 val2 = args[1]->val_decimal(&value2);
2240
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 203580 times.
203784 if ((null_value = args[1]->null_value)) return nullptr;
2241
2242
2/4
✓ Branch 0 taken 203580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 203580 times.
✗ Branch 3 not taken.
203580 if (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2243
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203580 times.
203580 decimal_value, val1, val2)) > 3) {
2244 return error_decimal(decimal_value);
2245 }
2246 /*
2247 Allow sign mismatch only if sql_mode includes MODE_NO_UNSIGNED_SUBTRACTION
2248 See Item_func_minus::resolve_type().
2249 */
2250
6/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 203575 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 203577 times.
203580 if (unsigned_flag && decimal_value->sign()) {
2251
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 raise_decimal_overflow();
2252 3 return error_decimal(decimal_value);
2253 }
2254 203577 return decimal_value;
2255 203942 }
2256
2257 1681209 double Item_func_mul::real_op() {
2258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1681209 times.
1681209 assert(fixed == 1);
2259 1681209 double val1 = args[0]->val_real();
2260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1681212 times.
1681210 if (current_thd->is_error()) return error_real();
2261 1681212 double val2 = args[1]->val_real();
2262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1681212 times.
1681212 if (current_thd->is_error()) return error_real();
2263
2264
5/6
✓ Branch 0 taken 1681210 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1681210 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1681210 times.
1681212 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2265 1681210 double value = val1 * val2;
2266 1681210 return check_float_overflow(value);
2267 }
2268
2269 1343089 longlong Item_func_mul::int_op() {
2270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1343089 times.
1343089 assert(fixed == 1);
2271 1343089 longlong a = args[0]->val_int();
2272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1343104 times.
1343105 if (current_thd->is_error()) return error_int();
2273 1343104 longlong b = args[1]->val_int();
2274
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1343102 times.
1343103 if (current_thd->is_error()) return error_int();
2275 longlong res;
2276 ulonglong res0, res1;
2277
2278
6/6
✓ Branch 0 taken 1343002 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 73 times.
✓ Branch 3 taken 1342929 times.
✓ Branch 4 taken 173 times.
✓ Branch 5 taken 1342929 times.
1343102 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
2279
2280
4/4
✓ Branch 0 taken 1189988 times.
✓ Branch 1 taken 152941 times.
✓ Branch 2 taken 15084 times.
✓ Branch 3 taken 1174904 times.
1342929 if (a == 0 || b == 0) return 0;
2281
2282 /*
2283 First check whether the result can be represented as a
2284 (bool unsigned_flag, longlong value) pair, then check if it is compatible
2285 with this Item's unsigned_flag by calling check_integer_overflow().
2286
2287 Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then
2288 a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 +
2289 + (a1 * b0 + a0 * b1) * 2^32 + a0 * b0;
2290 We can determine if the above sum overflows the ulonglong range by
2291 sequentially checking the following conditions:
2292 1. If both a1 and b1 are non-zero.
2293 2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX.
2294 3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than
2295 ULLONG_MAX.
2296
2297 Since we also have to take the unsigned_flag for a and b into account,
2298 it is easier to first work with absolute values and set the
2299 correct sign later.
2300
2301 We handle INT_MIN64 == -9223372036854775808 specially first,
2302 to avoid UBSAN warnings.
2303 */
2304
4/4
✓ Branch 0 taken 874551 times.
✓ Branch 1 taken 300353 times.
✓ Branch 2 taken 390 times.
✓ Branch 3 taken 874161 times.
1174904 const bool a_negative = (!args[0]->unsigned_flag && a < 0);
2305
4/4
✓ Branch 0 taken 1170280 times.
✓ Branch 1 taken 4624 times.
✓ Branch 2 taken 2162 times.
✓ Branch 3 taken 1168118 times.
1174904 const bool b_negative = (!args[1]->unsigned_flag && b < 0);
2306
2307 1174904 const bool res_unsigned = (a_negative == b_negative);
2308
2309
4/4
✓ Branch 0 taken 390 times.
✓ Branch 1 taken 1174514 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 386 times.
1174904 if (a_negative && a == INT_MIN64) {
2310
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (b == 1) return check_integer_overflow(a, res_unsigned);
2311 3 return raise_integer_overflow();
2312 }
2313
2314
4/4
✓ Branch 0 taken 2161 times.
✓ Branch 1 taken 1172739 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2157 times.
1174900 if (b_negative && b == INT_MIN64) {
2315
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (a == 1) return check_integer_overflow(b, res_unsigned);
2316 3 return raise_integer_overflow();
2317 }
2318
2319
2/2
✓ Branch 0 taken 385 times.
✓ Branch 1 taken 1174511 times.
1174896 if (a_negative) {
2320 385 a = -a;
2321 }
2322
2/2
✓ Branch 0 taken 2157 times.
✓ Branch 1 taken 1172739 times.
1174896 if (b_negative) {
2323 2157 b = -b;
2324 }
2325
2326 1174896 ulong a0 = 0xFFFFFFFFUL & a;
2327 1174896 ulong a1 = ((ulonglong)a) >> 32;
2328 1174896 ulong b0 = 0xFFFFFFFFUL & b;
2329 1174896 ulong b1 = ((ulonglong)b) >> 32;
2330
2331
4/4
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 1174739 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 156 times.
1174896 if (a1 && b1) goto err;
2332
2333 1174895 res1 = (ulonglong)a1 * b0 + (ulonglong)a0 * b1;
2334
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1174888 times.
1174895 if (res1 > 0xFFFFFFFFUL) goto err;
2335
2336 1174888 res1 = res1 << 32;
2337 1174888 res0 = (ulonglong)a0 * b0;
2338
2339
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1174875 times.
1174888 if (test_if_sum_overflows_ull(res1, res0)) goto err;
2340 1174875 res = res1 + res0;
2341
2342
2/2
✓ Branch 0 taken 2366 times.
✓ Branch 1 taken 1172509 times.
1174875 if (a_negative != b_negative) {
2343
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 2281 times.
2366 if ((ulonglong)res > (ulonglong)LLONG_MAX) goto err;
2344 2281 res = -res;
2345 }
2346
2347 1174790 return check_integer_overflow(res, res_unsigned);
2348
2349 94 err:
2350 94 return raise_integer_overflow();
2351 }
2352
2353 /** See Item_func_plus::decimal_op for comments. */
2354
2355 381022 my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value) {
2356 381022 my_decimal value1, *val1;
2357 381022 my_decimal value2, *val2;
2358
1/2
✓ Branch 0 taken 381022 times.
✗ Branch 1 not taken.
381022 val1 = args[0]->val_decimal(&value1);
2359
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 380818 times.
381022 if ((null_value = args[0]->null_value)) return nullptr;
2360
1/2
✓ Branch 0 taken 380818 times.
✗ Branch 1 not taken.
380818 val2 = args[1]->val_decimal(&value2);
2361
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 380695 times.
380818 if ((null_value = args[1]->null_value)) return nullptr;
2362
2363
2/4
✓ Branch 0 taken 380695 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 380695 times.
✗ Branch 3 not taken.
380695 if (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
2364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380695 times.
380695 decimal_value, val1, val2)) > 3) {
2365 return error_decimal(decimal_value);
2366 }
2367 380695 return decimal_value;
2368 381022 }
2369
2370 225778 void Item_func_mul::result_precision() {
2371 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2372
2/2
✓ Branch 0 taken 207713 times.
✓ Branch 1 taken 18065 times.
225778 if (result_type() == INT_RESULT)
2373 207713 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2374 else
2375 18065 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2376 225778 decimals = min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
2377
2/4
✓ Branch 0 taken 225778 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 225778 times.
✗ Branch 3 not taken.
225778 uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
2378 225778 uint precision = min<uint>(est_prec, DECIMAL_MAX_PRECISION);
2379 451556 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2380 225778 unsigned_flag);
2381 225778 }
2382
2383 6282 double Item_func_div_base::real_op() {
2384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6282 times.
6282 assert(fixed);
2385 6282 double val1 = args[0]->val_real();
2386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6282 times.
6282 if (current_thd->is_error()) return error_real();
2387 6282 double val2 = args[1]->val_real();
2388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6282 times.
6282 if (current_thd->is_error()) return error_real();
2389
2390
5/6
✓ Branch 0 taken 6282 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 6269 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 6269 times.
6282 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2391
2/2
✓ Branch 0 taken 5043 times.
✓ Branch 1 taken 1226 times.
6269 if (val2 == 0.0) {
2392 5043 signal_divide_by_null();
2393 5043 return 0.0;
2394 }
2395 1226 return check_float_overflow(val1 / val2);
2396 }
2397
2398 1240916 my_decimal *Item_func_div_base::decimal_op(my_decimal *decimal_value) {
2399 1240916 my_decimal value1, *val1;
2400 1240916 my_decimal value2, *val2;
2401 int err;
2402
2403
1/2
✓ Branch 0 taken 1240916 times.
✗ Branch 1 not taken.
1240916 val1 = args[0]->val_decimal(&value1);
2404
2/2
✓ Branch 0 taken 6327 times.
✓ Branch 1 taken 1234589 times.
1240916 if ((null_value = args[0]->null_value)) return nullptr;
2405
1/2
✓ Branch 0 taken 1234589 times.
✗ Branch 1 not taken.
1234589 val2 = args[1]->val_decimal(&value2);
2406
2/2
✓ Branch 0 taken 940 times.
✓ Branch 1 taken 1233649 times.
1234589 if ((null_value = args[1]->null_value)) return nullptr;
2407
2408
1/2
✓ Branch 0 taken 1233649 times.
✗ Branch 1 not taken.
1233649 if ((err = check_decimal_overflow(
2409 my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW & ~E_DEC_DIV_ZERO,
2410
3/4
✓ Branch 0 taken 1233649 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5744 times.
✓ Branch 3 taken 1227905 times.
2467298 decimal_value, val1, val2, m_prec_increment))) > 3) {
2411
2/4
✓ Branch 0 taken 5744 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5744 times.
✗ Branch 3 not taken.
5744 if (err == E_DEC_DIV_ZERO) signal_divide_by_null();
2412 5744 return error_decimal(decimal_value);
2413 }
2414 1227905 return decimal_value;
2415 1240916 }
2416
2417 1121944 void Item_func_div::result_precision() {
2418 1121944 uint precision = min<uint>(
2419 1121944 args[0]->decimal_precision() + args[1]->decimals + m_prec_increment,
2420
1/2
✓ Branch 0 taken 1121944 times.
✗ Branch 1 not taken.
1121944 DECIMAL_MAX_PRECISION);
2421
2422
3/4
✓ Branch 0 taken 648132 times.
✓ Branch 1 taken 473812 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 648132 times.
1121944 if (result_type() == DECIMAL_RESULT) assert(precision > 0);
2423
2424 /* Integer operations keep unsigned_flag if one of arguments is unsigned */
2425
2/2
✓ Branch 0 taken 473812 times.
✓ Branch 1 taken 648132 times.
1121944 if (result_type() == INT_RESULT)
2426 473812 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2427 else
2428 648132 unsigned_flag = args[0]->unsigned_flag & args[1]->unsigned_flag;
2429 1121944 decimals = min<uint>(args[0]->decimals + m_prec_increment, DECIMAL_MAX_SCALE);
2430 2243888 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2431 1121944 unsigned_flag);
2432 1121944 }
2433
2434 849629 void Item_func_div_int::result_precision() {
2435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 849629 times.
849629 assert(result_type() == INT_RESULT);
2436
2437 // Integer operations keep unsigned_flag if one of arguments is unsigned
2438 849629 unsigned_flag = args[0]->unsigned_flag | args[1]->unsigned_flag;
2439
2440 849629 uint arg0_decimals = args[0]->decimals;
2441
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 849595 times.
849629 if (arg0_decimals == DECIMAL_NOT_SPECIFIED) arg0_decimals = 0;
2442 849629 uint arg1_decimals = args[1]->decimals;
2443
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 849590 times.
849629 if (arg1_decimals == DECIMAL_NOT_SPECIFIED)
2444 39 arg1_decimals = args[1]->decimal_precision();
2445
2446 uint precision =
2447 849629 min<uint>(args[0]->decimal_precision() - arg0_decimals + arg1_decimals,
2448
1/2
✓ Branch 0 taken 849629 times.
✗ Branch 1 not taken.
849629 MY_INT64_NUM_DECIMAL_DIGITS);
2449
2450 849629 max_length =
2451 849629 my_decimal_precision_to_length_no_truncation(precision, 0, unsigned_flag);
2452 849629 }
2453
2454 566296 bool Item_func_div::resolve_type(THD *thd) {
2455
1/2
✓ Branch 0 taken 566296 times.
✗ Branch 1 not taken.
566296 DBUG_TRACE;
2456 566296 m_prec_increment = thd->variables.div_precincrement;
2457
3/4
✓ Branch 0 taken 566296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 566293 times.
566296 if (Item_num_op::resolve_type(thd)) return true;
2458
2459
3/4
✓ Branch 0 taken 5321 times.
✓ Branch 1 taken 473812 times.
✓ Branch 2 taken 87160 times.
✗ Branch 3 not taken.
566293 switch (hybrid_type) {
2460 5321 case REAL_RESULT: {
2461 5321 decimals = max(args[0]->decimals, args[1]->decimals) + m_prec_increment;
2462 5321 decimals = min(decimals, uint8(DECIMAL_NOT_SPECIFIED));
2463 5321 uint tmp = float_length(decimals);
2464
2/2
✓ Branch 0 taken 5269 times.
✓ Branch 1 taken 52 times.
5321 if (decimals == DECIMAL_NOT_SPECIFIED)
2465 5269 max_length = tmp;
2466 else {
2467 52 max_length = args[0]->max_length - args[0]->decimals + decimals;
2468 52 max_length = min(max_length, tmp);
2469 }
2470 5321 break;
2471 }
2472 473812 case INT_RESULT:
2473 473812 set_data_type(MYSQL_TYPE_NEWDECIMAL);
2474 473812 hybrid_type = DECIMAL_RESULT;
2475
3/8
✓ Branch 0 taken 473812 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 473812 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 473812 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
473812 DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
2476
1/2
✓ Branch 0 taken 473812 times.
✗ Branch 1 not taken.
473812 result_precision();
2477 473812 break;
2478 87160 case DECIMAL_RESULT:
2479
1/2
✓ Branch 0 taken 87160 times.
✗ Branch 1 not taken.
87160 result_precision();
2480 87160 break;
2481 default:
2482 assert(0);
2483 }
2484 566293 set_nullable(true); // division by zero
2485 566293 return false;
2486 566296 }
2487
2488 955644 longlong Item_func_div_base::int_op() {
2489
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955644 times.
955644 assert(fixed);
2490
2491 /*
2492 Perform division using DECIMAL math if either of the operands has a
2493 non-integer type
2494 */
2495
4/4
✓ Branch 0 taken 955467 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 955452 times.
1911111 if (args[0]->result_type() != INT_RESULT ||
2496
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 955452 times.
955467 args[1]->result_type() != INT_RESULT) {
2497 192 my_decimal tmp;
2498
1/2
✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
192 my_decimal *val0p = args[0]->val_decimal(&tmp);
2499
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 190 times.
192 if ((null_value = args[0]->null_value)) return 0;
2500
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 my_decimal val0 = *val0p;
2501
2502
1/2
✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
190 my_decimal *val1p = args[1]->val_decimal(&tmp);
2503
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 183 times.
190 if ((null_value = args[1]->null_value)) return 0;
2504
1/2
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
183 my_decimal val1 = *val1p;
2505
2506 int err;
2507
1/2
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
183 if ((err = my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, &val0,
2508
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 180 times.
183 &val1, 0)) > 3) {
2509
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (err == E_DEC_DIV_ZERO) signal_divide_by_null();
2510 3 return 0;
2511 }
2512
2513 180 my_decimal truncated;
2514 180 const bool do_truncate = true;
2515
2/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 180 times.
180 if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated))
2516 assert(false);
2517
2518 longlong res;
2519
3/4
✓ Branch 0 taken 180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 174 times.
180 if (my_decimal2int(E_DEC_FATAL_ERROR, &truncated, unsigned_flag, &res) &
2520 E_DEC_OVERFLOW)
2521
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 raise_integer_overflow();
2522 180 return res;
2523 192 }
2524
2525 955452 longlong val0 = args[0]->val_int();
2526 955452 longlong val1 = args[1]->val_int();
2527 bool val0_negative, val1_negative, res_negative;
2528 ulonglong uval0, uval1, res;
2529
6/6
✓ Branch 0 taken 955361 times.
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 955360 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 955360 times.
955452 if ((null_value = (args[0]->null_value || args[1]->null_value))) return 0;
2530
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 955356 times.
955360 if (val1 == 0) {
2531 4 signal_divide_by_null();
2532 4 return 0;
2533 }
2534
2535
4/4
✓ Branch 0 taken 955285 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 1325 times.
✓ Branch 3 taken 953960 times.
955356 val0_negative = !args[0]->unsigned_flag && val0 < 0;
2536
3/4
✓ Branch 0 taken 955356 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 955352 times.
955356 val1_negative = !args[1]->unsigned_flag && val1 < 0;
2537 955356 res_negative = val0_negative != val1_negative;
2538
4/4
✓ Branch 0 taken 1325 times.
✓ Branch 1 taken 954031 times.
✓ Branch 2 taken 1323 times.
✓ Branch 3 taken 2 times.
955356 uval0 = (ulonglong)(val0_negative && val0 != LLONG_MIN ? -val0 : val0);
2539
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 955352 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
955356 uval1 = (ulonglong)(val1_negative && val1 != LLONG_MIN ? -val1 : val1);
2540 955356 res = uval0 / uval1;
2541
2/2
✓ Branch 0 taken 1325 times.
✓ Branch 1 taken 954031 times.
955356 if (res_negative) {
2542
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1324 times.
1325 if (res > (ulonglong)LLONG_MAX) return raise_integer_overflow();
2543 1324 res = (ulonglong)(-(longlong)res);
2544 }
2545 955355 return check_integer_overflow(res, !res_negative);
2546 }
2547
2548 849629 bool Item_func_div_int::resolve_type(THD *thd) {
2549 // Integer division forces result to be integer, so force arguments
2550 // that are parameters to be integer as well.
2551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 849629 times.
849629 if (param_type_uses_non_param(thd, MYSQL_TYPE_LONGLONG)) return true;
2552
2553
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 849626 times.
849629 if (Item_func_div_base::resolve_type(thd)) return true;
2554 849626 set_nullable(true); // division by zero
2555
2556 849626 return false;
2557 }
2558
2559 849629 void Item_func_div_int::set_numeric_type() {
2560 849629 set_data_type_longlong();
2561 849629 hybrid_type = INT_RESULT;
2562 849629 result_precision();
2563 849629 }
2564
2565 3712887 longlong Item_func_mod::int_op() {
2566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3712887 times.
3712887 assert(fixed == 1);
2567 3712887 longlong val0 = args[0]->val_int();
2568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3712889 times.
3712889 if (current_thd->is_error()) return error_int();
2569 3712889 longlong val1 = args[1]->val_int();
2570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3712889 times.
3712889 if (current_thd->is_error()) return error_int();
2571 bool val0_negative, val1_negative;
2572 ulonglong uval0, uval1;
2573 ulonglong res;
2574
2575
6/6
✓ Branch 0 taken 3708095 times.
✓ Branch 1 taken 4794 times.
✓ Branch 2 taken 6565 times.
✓ Branch 3 taken 3701530 times.
✓ Branch 4 taken 11359 times.
✓ Branch 5 taken 3701530 times.
3712889 if ((null_value = args[0]->null_value || args[1]->null_value))
2576 11359 return 0; /* purecov: inspected */
2577
2/2
✓ Branch 0 taken 3988 times.
✓ Branch 1 taken 3697542 times.
3701530 if (val1 == 0) {
2578 3988 signal_divide_by_null();
2579 3988 return 0;
2580 }
2581
2582 /*
2583 '%' is calculated by integer division internally. Since dividing
2584 LLONG_MIN by -1 generates SIGFPE, we calculate using unsigned values and
2585 then adjust the sign appropriately.
2586 */
2587
4/4
✓ Branch 0 taken 3604819 times.
✓ Branch 1 taken 92723 times.
✓ Branch 2 taken 4215 times.
✓ Branch 3 taken 3600604 times.
3697542 val0_negative = !args[0]->unsigned_flag && val0 < 0;
2588
4/4
✓ Branch 0 taken 3695366 times.
✓ Branch 1 taken 2176 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 3695301 times.
3697542 val1_negative = !args[1]->unsigned_flag && val1 < 0;
2589
4/4
✓ Branch 0 taken 4215 times.
✓ Branch 1 taken 3693327 times.
✓ Branch 2 taken 4212 times.
✓ Branch 3 taken 3 times.
3697542 uval0 = (ulonglong)(val0_negative && val0 != LLONG_MIN ? -val0 : val0);
2590
3/4
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 3697477 times.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
3697542 uval1 = (ulonglong)(val1_negative && val1 != LLONG_MIN ? -val1 : val1);
2591 3697542 res = uval0 % uval1;
2592 MY_COMPILER_DIAGNOSTIC_PUSH()
2593 // Suppress warning C4146 unary minus operator applied to unsigned type,
2594 // result still unsigned
2595 MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(4146)
2596
2/2
✓ Branch 0 taken 4215 times.
✓ Branch 1 taken 3693327 times.
3697542 return check_integer_overflow(val0_negative ? -res : res, !val0_negative);
2597 MY_COMPILER_DIAGNOSTIC_POP()
2598 }
2599
2600 100251 double Item_func_mod::real_op() {
2601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100251 times.
100251 assert(fixed == 1);
2602 100251 double val1 = args[0]->val_real();
2603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100251 times.
100251 if (current_thd->is_error()) return error_real();
2604 100251 double val2 = args[1]->val_real();
2605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100251 times.
100251 if (current_thd->is_error()) return error_real();
2606
2607
6/6
✓ Branch 0 taken 100231 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 100213 times.
✓ Branch 4 taken 38 times.
✓ Branch 5 taken 100213 times.
100251 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0.0;
2608
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 100209 times.
100213 if (val2 == 0.0) {
2609 4 signal_divide_by_null();
2610 4 return 0.0;
2611 }
2612 100209 return fmod(val1, val2);
2613 }
2614
2615 62 my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value) {
2616 62 my_decimal value1, *val1;
2617 62 my_decimal value2, *val2;
2618
2619
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 val1 = args[0]->val_decimal(&value1);
2620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if ((null_value = args[0]->null_value)) return nullptr;
2621
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 val2 = args[1]->val_decimal(&value2);
2622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if ((null_value = args[1]->null_value)) return nullptr;
2623
3/5
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
62 switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
2624 val1, val2)) {
2625 53 case E_DEC_TRUNCATED:
2626 case E_DEC_OK:
2627 53 return decimal_value;
2628 9 case E_DEC_DIV_ZERO:
2629
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 signal_divide_by_null();
2630 [[fallthrough]];
2631 9 default:
2632 9 null_value = true;
2633 9 return nullptr;
2634 }
2635 62 }
2636
2637 135934 void Item_func_mod::result_precision() {
2638 135934 decimals = max(args[0]->decimals, args[1]->decimals);
2639 uint precision =
2640
1/2
✓ Branch 0 taken 135934 times.
✗ Branch 1 not taken.
135934 max(args[0]->decimal_precision(), args[1]->decimal_precision());
2641
2642 271868 max_length = my_decimal_precision_to_length_no_truncation(precision, decimals,
2643 135934 unsigned_flag);
2644
2645 // Increase max_length if we have: signed % unsigned(precision == scale)
2646
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 135563 times.
135566 if (!args[0]->unsigned_flag && args[1]->unsigned_flag &&
2647
5/6
✓ Branch 0 taken 135566 times.
✓ Branch 1 taken 368 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 135934 times.
271502 args[0]->max_length <= args[1]->max_length &&
2648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 args[1]->decimals == args[1]->decimal_precision()) {
2649 max_length += 1;
2650 }
2651 135934 }
2652
2653 144143 bool Item_func_mod::resolve_type(THD *thd) {
2654
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 144140 times.
144143 if (Item_num_op::resolve_type(thd)) return true;
2655 144140 set_nullable(true);
2656 144140 unsigned_flag = args[0]->unsigned_flag;
2657 144140 return false;
2658 }
2659
2660 2049 double Item_func_neg::real_op() {
2661 2049 double value = args[0]->val_real();
2662 2049 null_value = args[0]->null_value;
2663 2049 return -value;
2664 }
2665
2666 155895 longlong Item_func_neg::int_op() {
2667 155895 longlong value = args[0]->val_int();
2668
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 155874 times.
155895 if ((null_value = args[0]->null_value)) return 0;
2669
4/4
✓ Branch 0 taken 485 times.
✓ Branch 1 taken 155389 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 484 times.
155874 if (args[0]->unsigned_flag && (ulonglong)value > (ulonglong)LLONG_MAX + 1ULL)
2670 1 return raise_integer_overflow();
2671 // For some platforms we need special handling of LLONG_MIN to
2672 // guarantee overflow.
2673
5/6
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 155385 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 484 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
155873 if (value == LLONG_MIN && !args[0]->unsigned_flag && !unsigned_flag)
2674 4 return raise_integer_overflow();
2675 // Avoid doing '-value' below, it is undefined.
2676
4/6
✓ Branch 0 taken 484 times.
✓ Branch 1 taken 155385 times.
✓ Branch 2 taken 484 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 484 times.
✗ Branch 5 not taken.
155869 if (value == LLONG_MIN && args[0]->unsigned_flag && !unsigned_flag)
2677 484 return LLONG_MIN;
2678
3/4
✓ Branch 0 taken 155385 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8406 times.
✓ Branch 3 taken 146979 times.
155385 return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
2679 }
2680
2681 3808 my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value) {
2682
1/2
✓ Branch 0 taken 3808 times.
✗ Branch 1 not taken.
3808 my_decimal val, *value = args[0]->val_decimal(&val);
2683
1/2
✓ Branch 0 taken 3808 times.
✗ Branch 1 not taken.
3808 if (!(null_value = args[0]->null_value)) {
2684
1/2
✓ Branch 0 taken 3808 times.
✗ Branch 1 not taken.
3808 my_decimal2decimal(value, decimal_value);
2685
1/2
✓ Branch 0 taken 3808 times.
✗ Branch 1 not taken.
3808 my_decimal_neg(decimal_value);
2686 3808 return decimal_value;
2687 }
2688 return nullptr;
2689 3808 }
2690
2691 143557 void Item_func_neg::fix_num_length_and_dec() {
2692 143557 decimals = args[0]->decimals;
2693
2/2
✓ Branch 0 taken 468 times.
✓ Branch 1 taken 143089 times.
143557 max_length = args[0]->max_length + (args[0]->unsigned_flag ? 1 : 0);
2694 // Booleans have max_length = 1, but need to add the minus sign
2695
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 143552 times.
143557 if (max_length == 1) max_length++;
2696 143557 }
2697
2698 143557 bool Item_func_neg::resolve_type(THD *thd) {
2699
1/2
✓ Branch 0 taken 143558 times.
✗ Branch 1 not taken.
143557 DBUG_TRACE;
2700
3/4
✓ Branch 0 taken 143557 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 143556 times.
143558 if (Item_func_num1::resolve_type(thd)) return true;
2701 /*
2702 If this is in integer context keep the context as integer if possible
2703 (This is how multiplication and other integer functions works)
2704 Use val() to get value as arg_type doesn't mean that item is
2705 Item_int or Item_real due to existence of Item_param.
2706 */
2707
7/8
✓ Branch 0 taken 139881 times.
✓ Branch 1 taken 3675 times.
✓ Branch 2 taken 139881 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131989 times.
✓ Branch 5 taken 7892 times.
✓ Branch 6 taken 131987 times.
✓ Branch 7 taken 11569 times.
275545 if (hybrid_type == INT_RESULT && args[0]->const_item() &&
2708
3/4
✓ Branch 0 taken 131989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 131987 times.
✓ Branch 3 taken 2 times.
131989 args[0]->may_eval_const_item(thd)) {
2709
1/2
✓ Branch 0 taken 131987 times.
✗ Branch 1 not taken.
131987 longlong val = args[0]->val_int();
2710
6/6
✓ Branch 0 taken 772 times.
✓ Branch 1 taken 131215 times.
✓ Branch 2 taken 310 times.
✓ Branch 3 taken 462 times.
✓ Branch 4 taken 468 times.
✓ Branch 5 taken 131519 times.
132297 if ((ulonglong)val >= (ulonglong)LLONG_MIN &&
2711 310 ((ulonglong)val != (ulonglong)LLONG_MIN ||
2712
3/4
✓ Branch 0 taken 310 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 304 times.
310 args[0]->type() != INT_ITEM)) {
2713 /*
2714 Ensure that result is converted to DECIMAL, as longlong can't hold
2715 the negated number
2716 */
2717 468 unsigned_flag = false;
2718
2/4
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
468 set_data_type_decimal(args[0]->decimal_precision(), 0);
2719 468 hybrid_type = DECIMAL_RESULT;
2720
3/8
✓ Branch 0 taken 468 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 468 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 468 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
468 DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
2721 }
2722 }
2723 143556 unsigned_flag = false;
2724 143556 return false;
2725 143557 }
2726
2727 201 double Item_func_abs::real_op() {
2728 201 double value = args[0]->val_real();
2729 201 null_value = args[0]->null_value;
2730 201 return fabs(value);
2731 }
2732
2733 638117 longlong Item_func_abs::int_op() {
2734 638117 longlong value = args[0]->val_int();
2735
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 637942 times.
638117 if ((null_value = args[0]->null_value)) return 0;
2736
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 637939 times.
637942 if (unsigned_flag) return value;
2737 /* -LLONG_MIN = LLONG_MAX + 1 => outside of signed longlong range */
2738
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 637938 times.
637939 if (value == LLONG_MIN) return raise_integer_overflow();
2739 637938 return (value >= 0) ? value : -value;
2740 }
2741
2742 7 my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value) {
2743
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 my_decimal val, *value = args[0]->val_decimal(&val);
2744
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (!(null_value = args[0]->null_value)) {
2745
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 my_decimal2decimal(value, decimal_value);
2746
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 if (decimal_value->sign()) my_decimal_neg(decimal_value);
2747 6 return decimal_value;
2748 }
2749 1 return nullptr;
2750 7 }
2751
2752 2575 bool Item_func_abs::resolve_type(THD *thd) {
2753
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2574 times.
2575 if (Item_func_num1::resolve_type(thd)) return true;
2754 2574 unsigned_flag = args[0]->unsigned_flag;
2755 2574 return false;
2756 }
2757
2758 1100 bool Item_dec_func::resolve_type(THD *thd) {
2759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1100 times.
1100 if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DOUBLE)) return true;
2760 1100 decimals = DECIMAL_NOT_SPECIFIED;
2761 1100 max_length = float_length(decimals);
2762 1100 set_nullable(true);
2763 1100 return reject_geometry_args(arg_count, args, this);
2764 }
2765
2766 /** Gateway to natural LOG function. */
2767 44 double Item_func_ln::val_real() {
2768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 assert(fixed == 1);
2769 44 double value = args[0]->val_real();
2770
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
44 if ((null_value = args[0]->null_value)) return 0.0;
2771
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 11 times.
43 if (value <= 0.0) {
2772 32 signal_invalid_argument_for_log();
2773 32 return 0.0;
2774 }
2775 11 return log(value);
2776 }
2777
2778 /**
2779 Extended but so slower LOG function.
2780
2781 We have to check if all values are > zero and first one is not one
2782 as these are the cases then result is not a number.
2783 */
2784 41 double Item_func_log::val_real() {
2785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 assert(fixed == 1);
2786 41 double value = args[0]->val_real();
2787
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
41 if ((null_value = args[0]->null_value)) return 0.0;
2788
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 32 times.
39 if (value <= 0.0) {
2789 7 signal_invalid_argument_for_log();
2790 7 return 0.0;
2791 }
2792
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (arg_count == 2) {
2793 16 double value2 = args[1]->val_real();
2794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if ((null_value = args[1]->null_value)) return 0.0;
2795
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 10 times.
16 if (value2 <= 0.0 || value == 1.0) {
2796 6 signal_invalid_argument_for_log();
2797 6 return 0.0;
2798 }
2799 10 return log(value2) / log(value);
2800 }
2801 16 return log(value);
2802 }
2803
2804 25 double Item_func_log2::val_real() {
2805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 assert(fixed == 1);
2806 25 double value = args[0]->val_real();
2807
2808
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
25 if ((null_value = args[0]->null_value)) return 0.0;
2809
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 if (value <= 0.0) {
2810 7 signal_invalid_argument_for_log();
2811 7 return 0.0;
2812 }
2813 16 return std::log2(value);
2814 }
2815
2816 31 double Item_func_log10::val_real() {
2817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 assert(fixed == 1);
2818 31 double value = args[0]->val_real();
2819
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if ((null_value = args[0]->null_value)) return 0.0;
2820
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 22 times.
30 if (value <= 0.0) {
2821 8 signal_invalid_argument_for_log();
2822 8 return 0.0;
2823 }
2824 22 return log10(value);
2825 }
2826
2827 45 double Item_func_exp::val_real() {
2828
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 assert(fixed == 1);
2829 45 double value = args[0]->val_real();
2830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 if ((null_value = args[0]->null_value)) return 0.0; /* purecov: inspected */
2831 45 return check_float_overflow(exp(value));
2832 }
2833
2834 808 double Item_func_sqrt::val_real() {
2835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 808 times.
808 assert(fixed == 1);
2836 808 double value = args[0]->val_real();
2837
6/6
✓ Branch 0 taken 773 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 750 times.
✓ Branch 4 taken 58 times.
✓ Branch 5 taken 750 times.
808 if ((null_value = (args[0]->null_value || value < 0)))
2838 58 return 0.0; /* purecov: inspected */
2839 750 return sqrt(value);
2840 }
2841
2842 7153 double Item_func_pow::val_real() {
2843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7153 times.
7153 assert(fixed == 1);
2844 7153 double value = args[0]->val_real();
2845 7153 double val2 = args[1]->val_real();
2846
3/6
✓ Branch 0 taken 7153 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7153 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7153 times.
7153 if ((null_value = (args[0]->null_value || args[1]->null_value)))
2847 return 0.0; /* purecov: inspected */
2848 7153 const double pow_result = pow(value, val2);
2849 7153 return check_float_overflow(pow_result);
2850 }
2851
2852 // Trigonometric functions
2853
2854 28 double Item_func_acos::val_real() {
2855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 assert(fixed == 1);
2856 /* One can use this to defer SELECT processing. */
2857
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 DEBUG_SYNC(current_thd, "before_acos_function");
2858 28 double value = args[0]->val_real();
2859
6/8
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 24 times.
28 if ((null_value = (args[0]->null_value || (value < -1.0 || value > 1.0))))
2860 4 return 0.0;
2861 24 return acos(value);
2862 }
2863
2864 33 double Item_func_asin::val_real() {
2865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 assert(fixed == 1);
2866 33 double value = args[0]->val_real();
2867
7/8
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 18 times.
33 if ((null_value = (args[0]->null_value || (value < -1.0 || value > 1.0))))
2868 15 return 0.0;
2869 18 return asin(value);
2870 }
2871
2872 41 double Item_func_atan::val_real() {
2873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 assert(fixed == 1);
2874 41 double value = args[0]->val_real();
2875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if ((null_value = args[0]->null_value)) return 0.0;
2876
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 20 times.
41 if (arg_count == 2) {
2877 21 double val2 = args[1]->val_real();
2878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if ((null_value = args[1]->null_value)) return 0.0;
2879 21 return check_float_overflow(atan2(value, val2));
2880 }
2881 20 return atan(value);
2882 }
2883
2884 18 double Item_func_cos::val_real() {
2885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 assert(fixed == 1);
2886 18 double value = args[0]->val_real();
2887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ((null_value = args[0]->null_value)) return 0.0;
2888 18 return cos(value);
2889 }
2890
2891 94 double Item_func_sin::val_real() {
2892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94 times.
94 assert(fixed == 1);
2893 94 double value = args[0]->val_real();
2894
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 93 times.
94 if ((null_value = args[0]->null_value)) return 0.0;
2895 93 return sin(value);
2896 }
2897
2898 19 double Item_func_tan::val_real() {
2899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 assert(fixed == 1);
2900 19 double value = args[0]->val_real();
2901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ((null_value = args[0]->null_value)) return 0.0;
2902 19 return check_float_overflow(tan(value));
2903 }
2904
2905 17 double Item_func_cot::val_real() {
2906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 assert(fixed == 1);
2907 17 double value = args[0]->val_real();
2908
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
17 if ((null_value = args[0]->null_value)) return 0.0;
2909 14 double val2 = tan(value);
2910
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5 times.
14 if (val2 == 0.0) {
2911 9 return raise_float_overflow();
2912 }
2913 5 return check_float_overflow(1.0 / val2);
2914 }
2915
2916 // Bitwise functions
2917
2918 90699 bool Item_func_bit::resolve_type(THD *thd) {
2919 90699 const bool second_arg = binary_result_requires_binary_second_arg();
2920 /*
2921 In ?&?, we assume varbinary; if integer is provided we'll re-prepare.
2922 To force var*binary*, we temporarily change the charset:
2923 */
2924 90699 const CHARSET_INFO *save_cs = thd->variables.collation_connection;
2925 90699 thd->variables.collation_connection = &my_charset_bin;
2926
2/2
✓ Branch 0 taken 30542 times.
✓ Branch 1 taken 60157 times.
90699 if (second_arg) {
2927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30542 times.
30542 if (param_type_uses_non_param(thd)) return true;
2928 } else {
2929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60157 times.
60157 if (param_type_is_default(thd, 0, 1)) return true;
2930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60157 times.
60157 if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true;
2931 }
2932 90699 thd->variables.collation_connection = save_cs;
2933
4/4
✓ Branch 0 taken 30542 times.
✓ Branch 1 taken 60157 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 90627 times.
90699 if (bit_func_returns_binary(args[0], second_arg ? args[1] : nullptr)) {
2934 72 hybrid_type = STRING_RESULT;
2935 72 set_data_type_string(
2936
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 22 times.
144 max<uint32>(args[0]->max_length, second_arg ? args[1]->max_length : 0U),
2937 &my_charset_bin);
2938 } else {
2939 90627 hybrid_type = INT_RESULT;
2940 90627 set_data_type_longlong();
2941 90627 unsigned_flag = true;
2942 }
2943 90699 return reject_geometry_args(arg_count, args, this);
2944 }
2945
2946 88228 longlong Item_func_bit::val_int() {
2947
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88228 times.
88228 assert(fixed);
2948
1/2
✓ Branch 0 taken 88228 times.
✗ Branch 1 not taken.
88228 if (hybrid_type == INT_RESULT)
2949 88228 return int_op();
2950 else {
2951 String *res;
2952 if (!(res = str_op(&str_value))) return 0;
2953
2954 int ovf_error;
2955 const char *from = res->ptr();
2956 size_t len = res->length();
2957 const char *end = from + len;
2958 return my_strtoll10(from, &end, &ovf_error);
2959 }
2960 }
2961
2962 6 double Item_func_bit::val_real() {
2963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 assert(fixed);
2964
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (hybrid_type == INT_RESULT)
2965 6 return static_cast<ulonglong>(int_op());
2966 else {
2967 String *res;
2968 if (!(res = str_op(&str_value))) return 0.0;
2969
2970 int ovf_error;
2971 const char *from = res->ptr();
2972 size_t len = res->length();
2973 const char *end = from + len;
2974 return my_strtod(from, &end, &ovf_error);
2975 }
2976 }
2977
2978 13090 my_decimal *Item_func_bit::val_decimal(my_decimal *decimal_value) {
2979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13090 times.
13090 assert(fixed);
2980
1/2
✓ Branch 0 taken 13090 times.
✗ Branch 1 not taken.
13090 if (hybrid_type == INT_RESULT)
2981 13090 return val_decimal_from_int(decimal_value);
2982 else
2983 return val_decimal_from_string(decimal_value);
2984 }
2985
2986 505 String *Item_func_bit::val_str(String *str) {
2987
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
505 assert(fixed);
2988
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 440 times.
505 if (hybrid_type == INT_RESULT) {
2989 65 longlong nr = int_op();
2990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (null_value) return nullptr;
2991 65 str->set_int(nr, unsigned_flag, collation.collation);
2992 65 return str;
2993 } else
2994 440 return str_op(str);
2995 }
2996
2997 // Shift-functions, same as << and >> in C/C++
2998
2999 /**
3000 Template function that evaluates the bitwise shift operation over integer
3001 arguments.
3002 @tparam to_left True if left-shift, false if right-shift
3003 */
3004 template <bool to_left>
3005 119616 longlong Item_func_shift::eval_int_op() {
3006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59808 times.
119616 assert(fixed);
3007 119616 ulonglong res = args[0]->val_uint();
3008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59808 times.
119616 if (args[0]->null_value) return error_int();
3009
3010 119616 ulonglong shift = args[1]->val_uint();
3011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59808 times.
119616 if (args[1]->null_value) return error_int();
3012
3013 119616 null_value = false;
3014
2/2
✓ Branch 0 taken 59793 times.
✓ Branch 1 taken 15 times.
119616 if (shift < sizeof(longlong) * 8)
3015 119586 return to_left ? (res << shift) : (res >> shift);
3016 30 return 0;
3017 }
3018
3019 /// Instantiations of the above
3020 template longlong Item_func_shift::eval_int_op<true>();
3021 template longlong Item_func_shift::eval_int_op<false>();
3022
3023 /**
3024 Template function that evaluates the bitwise shift operation over binary
3025 string arguments.
3026 @tparam to_left True if left-shift, false if right-shift
3027 */
3028 template <bool to_left>
3029 98 String *Item_func_shift::eval_str_op(String *) {
3030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
98 assert(fixed);
3031
3032 98 String tmp_str;
3033
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
98 String *arg = args[0]->val_str(&tmp_str);
3034
4/6
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
98 if (!arg || args[0]->null_value) return error_str();
3035
3036 96 ssize_t arg_length = arg->length();
3037 96 size_t shift =
3038
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
96 min(args[1]->val_uint(), static_cast<ulonglong>(arg_length) * 8);
3039
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
96 if (args[1]->null_value) return error_str();
3040
3041
2/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
96 if (tmp_value.alloc(arg->length())) return error_str();
3042
3043 96 tmp_value.length(arg_length);
3044 96 tmp_value.set_charset(&my_charset_bin);
3045 /*
3046 Example with left-shift-by-21-bits:
3047 |........|........|........|........|
3048 byte i byte i+1 byte i+2 byte i+3
3049 First (leftmost) bit has number 1.
3050 21 = 2*8 + 5.
3051 Bits of number 1-3 of byte 'i' receive bits 22-24 i.e. the last 3 bits of
3052 byte 'i+2'. So, take byte 'i+2', shift it left by 5 bits, that puts the
3053 last 3 bits of byte 'i+2' in bits 1-3, and 0s elsewhere.
3054 Bits of number 4-8 of byte 'i' receive bits 25-39 i.e. the first 5 bits of
3055 byte 'i+3'. So, take byte 'i+3', shift it right by 3 bits, that puts the
3056 first 5 bits of byte 'i+3' in bits 4-8, and 0s elsewhere.
3057 In total, do OR of both results.
3058 */
3059 96 size_t mod = shift % 8;
3060 96 size_t mod_complement = 8 - mod;
3061 96 ssize_t entire_bytes = shift / 8;
3062
3063 96 const unsigned char *from_c = pointer_cast<const unsigned char *>(arg->ptr());
3064 96 unsigned char *to_c = pointer_cast<unsigned char *>(tmp_value.c_ptr_quick());
3065
3066 if (to_left) {
3067 // Bytes of lower index are overwritten by bytes of higher index
3068
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 24 times.
552 for (ssize_t i = 0; i < arg_length; i++)
3069
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 24 times.
504 if (i + entire_bytes + 1 < arg_length)
3070 456 to_c[i] = (from_c[i + entire_bytes] << mod) |
3071 456 (from_c[i + entire_bytes + 1] >> mod_complement);
3072
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 else if (i + entire_bytes + 1 == arg_length)
3073 48 to_c[i] = from_c[i + entire_bytes] << mod;
3074 else
3075 to_c[i] = 0;
3076 } else {
3077 // Bytes of higher index are overwritten by bytes of lower index
3078
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 24 times.
552 for (ssize_t i = arg_length - 1; i >= 0; i--)
3079
2/2
✓ Branch 0 taken 228 times.
✓ Branch 1 taken 24 times.
504 if (i > entire_bytes)
3080 456 to_c[i] = (from_c[i - entire_bytes] >> mod) |
3081 456 (from_c[i - entire_bytes - 1] << mod_complement);
3082
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
48 else if (i == entire_bytes)
3083 48 to_c[i] = from_c[i - entire_bytes] >> mod;
3084 else
3085 to_c[i] = 0;
3086 }
3087
3088 96 null_value = false;
3089 96 return &tmp_value;
3090 98 }
3091
3092 /// Instantiations of the above
3093 template String *Item_func_shift::eval_str_op<true>(String *);
3094 template String *Item_func_shift::eval_str_op<false>(String *);
3095
3096 // Bit negation ('~')
3097
3098 23 longlong Item_func_bit_neg::int_op() {
3099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 assert(fixed);
3100 23 ulonglong res = (ulonglong)args[0]->val_int();
3101
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 22 times.
23 if (args[0]->null_value) return error_int();
3102 22 null_value = false;
3103 22 return ~res;
3104 }
3105
3106 55 String *Item_func_bit_neg::str_op(String *str) {
3107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 assert(fixed);
3108 55 String *res = args[0]->val_str(str);
3109
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
55 if (args[0]->null_value || !res) return error_str();
3110
3111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (tmp_value.alloc(res->length())) return error_str();
3112
3113 54 size_t arg_length = res->length();
3114 54 tmp_value.length(arg_length);
3115 54 tmp_value.set_charset(&my_charset_bin);
3116 54 const unsigned char *from_c = pointer_cast<const unsigned char *>(res->ptr());
3117 54 unsigned char *to_c = pointer_cast<unsigned char *>(tmp_value.c_ptr_quick());
3118 54 size_t i = 0;
3119
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 54 times.
117 while (i + sizeof(longlong) <= arg_length) {
3120 63 int8store(&to_c[i], ~(uint8korr(&from_c[i])));
3121 63 i += sizeof(longlong);
3122 }
3123
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 54 times.
117 while (i < arg_length) {
3124 63 to_c[i] = ~from_c[i];
3125 63 i++;
3126 }
3127
3128 54 null_value = false;
3129 54 return &tmp_value;
3130 }
3131
3132 /**
3133 Template function used to evaluate the bitwise operation over int arguments.
3134
3135 @param int_func The bitwise function.
3136 */
3137 template <class Int_func>
3138 56936 longlong Item_func_bit_two_param::eval_int_op(Int_func int_func) {
3139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28468 times.
56936 assert(fixed);
3140
1/2
✓ Branch 0 taken 28468 times.
✗ Branch 1 not taken.
56936 ulonglong arg0 = args[0]->val_uint();
3141
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 28460 times.
56936 if (args[0]->null_value) return error_int();
3142
1/2
✓ Branch 0 taken 28460 times.
✗ Branch 1 not taken.
56920 ulonglong arg1 = args[1]->val_uint();
3143
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 28456 times.
56920 if (args[1]->null_value) return error_int();
3144 56912 null_value = false;
3145 56912 return (longlong)int_func(arg0, arg1);
3146 }
3147
3148 /// Instantiations of the above
3149 template longlong Item_func_bit_two_param::eval_int_op<std::bit_or<ulonglong>>(
3150 std::bit_or<ulonglong>);
3151 template longlong Item_func_bit_two_param::eval_int_op<std::bit_and<ulonglong>>(
3152 std::bit_and<ulonglong>);
3153 template longlong Item_func_bit_two_param::eval_int_op<std::bit_xor<ulonglong>>(
3154 std::bit_xor<ulonglong>);
3155
3156 /**
3157 Template function that evaluates the bitwise operation over binary arguments.
3158 Checks that both arguments have same length and applies the bitwise operation
3159
3160 @param char_func The Bitwise function used to evaluate unsigned chars.
3161 @param int_func The Bitwise function used to evaluate unsigned long longs.
3162 */
3163 template <class Char_func, class Int_func>
3164 672 String *Item_func_bit_two_param::eval_str_op(String *, Char_func char_func,
3165 Int_func int_func) {
3166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
672 assert(fixed);
3167 672 String arg0_buff;
3168
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
672 String *s1 = args[0]->val_str(&arg0_buff);
3169
3170
2/6
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 336 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
672 if (args[0]->null_value || !s1) return error_str();
3171
3172 672 String arg1_buff;
3173
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
672 String *s2 = args[1]->val_str(&arg1_buff);
3174
3175
4/6
✓ Branch 0 taken 174 times.
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 174 times.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
672 if (args[1]->null_value || !s2) return error_str();
3176
3177 348 size_t arg_length = s1->length();
3178
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 171 times.
348 if (arg_length != s2->length()) {
3179
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 my_error(ER_INVALID_BITWISE_OPERANDS_SIZE, MYF(0), func_name());
3180
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
6 return error_str();
3181 }
3182
3183
2/6
✓ Branch 0 taken 171 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 171 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
342 if (tmp_value.alloc(arg_length)) return error_str();
3184
3185 342 tmp_value.length(arg_length);
3186 342 tmp_value.set_charset(&my_charset_bin);
3187
3188 342 const uchar *s1_c_p = pointer_cast<const uchar *>(s1->ptr());
3189 342 const uchar *s2_c_p = pointer_cast<const uchar *>(s2->ptr());
3190 342 char *res = tmp_value.ptr();
3191 342 size_t i = 0;
3192
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 171 times.
720 while (i + sizeof(longlong) <= arg_length) {
3193 378 int8store(&res[i], int_func(uint8korr(&s1_c_p[i]), uint8korr(&s2_c_p[i])));
3194 378 i += sizeof(longlong);
3195 }
3196
2/2
✓ Branch 0 taken 207 times.
✓ Branch 1 taken 171 times.
756 while (i < arg_length) {
3197 414 res[i] = char_func(s1_c_p[i], s2_c_p[i]);
3198 414 i++;
3199 }
3200
3201 342 null_value = false;
3202 342 return &tmp_value;
3203 672 }
3204
3205 /// Instantiations of the above
3206 template String *
3207 Item_func_bit_two_param::eval_str_op<std::bit_or<char>, std::bit_or<ulonglong>>(
3208 String *, std::bit_or<char>, std::bit_or<ulonglong>);
3209 template String *Item_func_bit_two_param::eval_str_op<
3210 std::bit_and<char>, std::bit_and<ulonglong>>(String *, std::bit_and<char>,
3211 std::bit_and<ulonglong>);
3212 template String *Item_func_bit_two_param::eval_str_op<
3213 std::bit_xor<char>, std::bit_xor<ulonglong>>(String *, std::bit_xor<char>,
3214 std::bit_xor<ulonglong>);
3215
3216 91311 bool Item::bit_func_returns_binary(const Item *a, const Item *b) {
3217 /*
3218 Checks if the bitwise function should return binary data.
3219 The conditions to return true are the following:
3220
3221 1. If there's only one argument(so b is nullptr),
3222 then a must be a [VAR]BINARY Item, different from the hex/bit/NULL literal.
3223
3224 2. If there are two arguments, both should be [VAR]BINARY
3225 and at least one of them should be different from the hex/bit/NULL literal
3226 */
3227 // Check if a is [VAR]BINARY Item
3228
2/2
✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 90122 times.
92500 bool a_is_binary = a->result_type() == STRING_RESULT &&
3229
2/2
✓ Branch 0 taken 1170 times.
✓ Branch 1 taken 19 times.
1189 a->collation.collation == &my_charset_bin;
3230 // Check if b is not null and is [VAR]BINARY Item
3231
4/4
✓ Branch 0 taken 30542 times.
✓ Branch 1 taken 60769 times.
✓ Branch 2 taken 201 times.
✓ Branch 3 taken 30341 times.
91512 bool b_is_binary = b && b->result_type() == STRING_RESULT &&
3232
2/2
✓ Branch 0 taken 195 times.
✓ Branch 1 taken 6 times.
201 b->collation.collation == &my_charset_bin;
3233
3234
6/6
✓ Branch 0 taken 1170 times.
✓ Branch 1 taken 90141 times.
✓ Branch 2 taken 603 times.
✓ Branch 3 taken 567 times.
✓ Branch 4 taken 122 times.
✓ Branch 5 taken 481 times.
92000 return a_is_binary && (!b || b_is_binary) &&
3235
5/6
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 575 times.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 42 times.
689 ((a->type() != Item::VARBIN_ITEM && a->type() != Item::NULL_ITEM) ||
3236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 (b && b->type() != Item::VARBIN_ITEM &&
3237
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
91311 b->type() != Item::NULL_ITEM));
3238 }
3239
3240 // Conversion functions
3241
3242 111646 bool Item_func_int_val::resolve_type_inner(THD *) {
3243
1/2
✓ Branch 0 taken 111646 times.
✗ Branch 1 not taken.
111646 DBUG_TRACE;
3244
3/10
✓ Branch 0 taken 111646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111646 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 111646 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
111646 DBUG_PRINT("info", ("name %s", func_name()));
3245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111646 times.
111646 assert(args[0]->data_type() != MYSQL_TYPE_INVALID);
3246
3247
3/4
✓ Branch 0 taken 111646 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 111642 times.
111646 if (reject_geometry_args(arg_count, args, this)) return true;
3248
3249
4/6
✓ Branch 0 taken 111642 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 101980 times.
✓ Branch 3 taken 85 times.
✓ Branch 4 taken 9577 times.
✗ Branch 5 not taken.
111642 switch (args[0]->result_type()) {
3250 101980 case STRING_RESULT:
3251 case REAL_RESULT:
3252
1/2
✓ Branch 0 taken 101980 times.
✗ Branch 1 not taken.
101980 set_data_type_double();
3253 101980 hybrid_type = REAL_RESULT;
3254 101980 break;
3255 85 case INT_RESULT:
3256
1/2
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
85 set_data_type_longlong();
3257 85 unsigned_flag = args[0]->unsigned_flag;
3258 85 hybrid_type = INT_RESULT;
3259 85 break;
3260 9577 case DECIMAL_RESULT: {
3261 // For historical reasons, CEILING and FLOOR convert DECIMAL inputs into
3262 // BIGINT (granted that they are small enough to fit) while ROUND and
3263 // TRUNCATE don't. As items are not yet evaluated at this point,
3264 // assumptions must be made about when a conversion from DECIMAL_RESULT to
3265 // INT_RESULT can be safely achieved.
3266 //
3267 // During the rounding operation, we account for signedness by always
3268 // assuming that the argument DECIMAL is signed. Additionally, since we
3269 // call set_data_type_decimal with a scale of 0, we must increment the
3270 // precision here, as the rounding operation may cause an increase in
3271 // order of magnitude.
3272
1/2
✓ Branch 0 taken 9577 times.
✗ Branch 1 not taken.
9577 int precision = args[0]->decimal_precision() - args[0]->decimals;
3273
2/2
✓ Branch 0 taken 9559 times.
✓ Branch 1 taken 18 times.
9577 if (args[0]->decimals != 0) ++precision;
3274
1/2
✓ Branch 0 taken 9577 times.
✗ Branch 1 not taken.
9577 set_data_type_decimal(precision, 0);
3275 9577 hybrid_type = DECIMAL_RESULT;
3276
3277 // The max_length of the biggest INT_RESULT, BIGINT, is 20 regardless of
3278 // signedness, as a minus sign will be counted as one digit. A DECIMAL of
3279 // length 20 could be bigger than the max BIGINT value, thus requiring a
3280 // length < 20. DECIMAL_LONGLONG_DIGITS value is 22, which is presumably
3281 // the sum of 20 digits, a minus sign and a decimal point; requiring -2
3282 // when considering the conversion.
3283
2/2
✓ Branch 0 taken 9540 times.
✓ Branch 1 taken 37 times.
9577 if (max_length < (DECIMAL_LONGLONG_DIGITS - 2)) {
3284
1/2
✓ Branch 0 taken 9540 times.
✗ Branch 1 not taken.
9540 set_data_type_longlong();
3285 9540 hybrid_type = INT_RESULT;
3286 }
3287
3288 9577 break;
3289 }
3290 default:
3291 assert(0);
3292 }
3293
3/14
✓ Branch 0 taken 111642 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 111642 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 111642 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
111642 DBUG_PRINT("info", ("Type: %s", (hybrid_type == REAL_RESULT
3294 ? "REAL_RESULT"
3295 : hybrid_type == DECIMAL_RESULT
3296 ? "DECIMAL_RESULT"
3297 : hybrid_type == INT_RESULT
3298 ? "INT_RESULT"
3299 : "--ILLEGAL!!!--")));
3300
3301 111642 return false;
3302 111646 }
3303
3304 293 longlong Item_func_ceiling::int_op() {
3305 longlong result;
3306
3/5
✓ Branch 0 taken 293 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 280 times.
✗ Branch 4 not taken.
293 switch (args[0]->result_type()) {
3307 13 case INT_RESULT:
3308
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 result = args[0]->val_int();
3309 13 null_value = args[0]->null_value;
3310 13 break;
3311 280 case DECIMAL_RESULT: {
3312 280 my_decimal dec_buf, *dec;
3313
2/4
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 280 times.
✗ Branch 3 not taken.
280 if ((dec = Item_func_ceiling::decimal_op(&dec_buf)))
3314
1/2
✓ Branch 0 taken 280 times.
✗ Branch 1 not taken.
280 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
3315 else
3316 result = 0;
3317 280 break;
3318 280 }
3319 default:
3320 result = (longlong)Item_func_ceiling::real_op();
3321 };
3322 293 return result;
3323 }
3324
3325 12 double Item_func_ceiling::real_op() {
3326 12 double value = args[0]->val_real();
3327 12 null_value = args[0]->null_value;
3328 12 return ceil(value);
3329 }
3330
3331 286 my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value) {
3332
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
286 my_decimal val, *value = args[0]->val_decimal(&val);
3333
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
286 if (!(null_value =
3334
1/2
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
572 (args[0]->null_value ||
3335
2/4
✓ Branch 0 taken 286 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 286 times.
286 my_decimal_ceiling(E_DEC_FATAL_ERROR, value, decimal_value) > 1)))
3336 286 return decimal_value;
3337 return nullptr;
3338 286 }
3339
3340 53475 longlong Item_func_floor::int_op() {
3341 longlong result;
3342
3/5
✓ Branch 0 taken 53475 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 53444 times.
✗ Branch 4 not taken.
53475 switch (args[0]->result_type()) {
3343 31 case INT_RESULT:
3344
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 result = args[0]->val_int();
3345 31 null_value = args[0]->null_value;
3346 31 break;
3347 53444 case DECIMAL_RESULT: {
3348 53444 my_decimal dec_buf, *dec;
3349
2/4
✓ Branch 0 taken 53444 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 53444 times.
✗ Branch 3 not taken.
53444 if ((dec = Item_func_floor::decimal_op(&dec_buf)))
3350
1/2
✓ Branch 0 taken 53444 times.
✗ Branch 1 not taken.
53444 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
3351 else
3352 result = 0;
3353 53444 break;
3354 53444 }
3355 default:
3356 result = (longlong)Item_func_floor::real_op();
3357 };
3358 53475 return result;
3359 }
3360
3361 637404 double Item_func_floor::real_op() {
3362 637404 double value = args[0]->val_real();
3363 637405 null_value = args[0]->null_value;
3364 637405 return floor(value);
3365 }
3366
3367 427601 my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value) {
3368
1/2
✓ Branch 0 taken 427601 times.
✗ Branch 1 not taken.
427601 my_decimal val, *value = args[0]->val_decimal(&val);
3369
1/2
✓ Branch 0 taken 427601 times.
✗ Branch 1 not taken.
427601 if (!(null_value =
3370
1/2
✓ Branch 0 taken 427601 times.
✗ Branch 1 not taken.
855202 (args[0]->null_value ||
3371
2/4
✓ Branch 0 taken 427601 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 427601 times.
427601 my_decimal_floor(E_DEC_FATAL_ERROR, value, decimal_value) > 1)))
3372 427601 return decimal_value;
3373 return nullptr;
3374 427601 }
3375
3376 90218 bool Item_func_round::resolve_type(THD *thd) {
3377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90218 times.
90218 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_NEWDECIMAL)) return true;
3378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90218 times.
90218 if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true;
3379
3380
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 90216 times.
90218 if (reject_geometry_args(arg_count, args, this)) return true;
3381
3382
3/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 79761 times.
✓ Branch 2 taken 10421 times.
✗ Branch 3 not taken.
90216 switch (args[0]->result_type()) {
3383 34 case INT_RESULT:
3384 34 set_data_type_longlong();
3385 34 unsigned_flag = args[0]->unsigned_flag;
3386 34 hybrid_type = INT_RESULT;
3387 34 break;
3388 79761 case DECIMAL_RESULT: {
3389 /*
3390 If the rounding precision is known at this stage (constant), use it
3391 to adjust the precision and scale of the result to the minimal
3392 values that will accommodate the answer. Otherwise, use the precision
3393 and scale from the first argument.
3394 If wanted scale is less than argument's scale, reduce it accordingly.
3395 When rounding, make sure to accommodate one extra digit in precision
3396 Example: ROUND(99.999, 2). Here, the type of the argument is
3397 DECIMAL(5, 3). The type of the result is DECIMAL(5,2), since the
3398 result of this operation is 100.00.
3399 Also make sure that precision is greater than zero.
3400 */
3401 longlong val1;
3402
5/6
✓ Branch 0 taken 79737 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 79737 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 79737 times.
✓ Branch 5 taken 24 times.
79761 if (args[1]->const_item() && args[1]->may_eval_const_item(thd)) {
3403 79737 val1 = args[1]->val_int();
3404
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 79735 times.
79737 if ((null_value = args[1]->is_null())) {
3405 2 val1 = 0;
3406 }
3407
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 79733 times.
79737 if (args[1]->unsigned_flag) {
3408
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (val1 > DECIMAL_MAX_SCALE || val1 < 0) val1 = DECIMAL_MAX_SCALE;
3409
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 79722 times.
79733 } else if (val1 > DECIMAL_MAX_SCALE) {
3410 11 val1 = DECIMAL_MAX_SCALE;
3411
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 79714 times.
79722 } else if (val1 < -DECIMAL_MAX_SCALE) {
3412 8 val1 = -DECIMAL_MAX_SCALE;
3413 }
3414 } else {
3415 24 val1 = args[0]->decimals;
3416 }
3417
3418 79761 uint8 precision = args[0]->decimal_precision();
3419 79761 uint8 new_scale = args[0]->decimals;
3420
2/2
✓ Branch 0 taken 67561 times.
✓ Branch 1 taken 12200 times.
79761 if (val1 <= 0) {
3421 67561 precision -= new_scale;
3422
2/2
✓ Branch 0 taken 67529 times.
✓ Branch 1 taken 32 times.
67561 if (!truncate) precision += 1;
3423 67561 new_scale = 0;
3424
2/2
✓ Branch 0 taken 6522 times.
✓ Branch 1 taken 5678 times.
12200 } else if (val1 < new_scale) {
3425 6522 precision -= (new_scale - val1);
3426
2/2
✓ Branch 0 taken 6506 times.
✓ Branch 1 taken 16 times.
6522 if (!truncate) precision += 1;
3427 6522 new_scale = val1;
3428 }
3429
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 79759 times.
79761 if (precision == 0) precision = 1;
3430 79761 set_data_type_decimal(precision, new_scale);
3431 79761 hybrid_type = DECIMAL_RESULT;
3432 79761 break;
3433 }
3434 10421 case REAL_RESULT:
3435 case STRING_RESULT:
3436 10421 set_data_type_double();
3437 10421 hybrid_type = REAL_RESULT;
3438 10421 break;
3439 default:
3440 assert(0); /* This result type isn't handled */
3441 }
3442 90216 return false;
3443 }
3444
3445 40892 double my_double_round(double value, longlong dec, bool dec_unsigned,
3446 bool truncate) {
3447
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40884 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
40892 bool dec_negative = (dec < 0) && !dec_unsigned;
3448 40892 int log_10_size = array_elements(log_10); // 309
3449
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40884 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 5 times.
40892 if (dec_negative && dec <= -log_10_size) return 0.0;
3450
3451
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 40884 times.
40889 ulonglong abs_dec = dec_negative ? -dec : dec;
3452
3453
2/2
✓ Branch 0 taken 24419 times.
✓ Branch 1 taken 16470 times.
40889 double tmp = (abs_dec < array_elements(log_10) ? log_10[abs_dec]
3454 16470 : pow(10.0, (double)abs_dec));
3455
3456 40889 double value_mul_tmp = value * tmp;
3457
6/6
✓ Branch 0 taken 40884 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 16481 times.
✓ Branch 3 taken 24403 times.
✓ Branch 4 taken 16481 times.
✓ Branch 5 taken 24408 times.
40889 if (!dec_negative && !std::isfinite(value_mul_tmp)) return value;
3458
3459 24408 double value_div_tmp = value / tmp;
3460
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 24344 times.
24408 if (truncate) {
3461
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if (value >= 0.0)
3462
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 63 times.
64 return dec < 0 ? floor(value_div_tmp) * tmp : floor(value_mul_tmp) / tmp;
3463 else
3464 return dec < 0 ? ceil(value_div_tmp) * tmp : ceil(value_mul_tmp) / tmp;
3465 }
3466
3467
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 24340 times.
24344 return dec < 0 ? rint(value_div_tmp) * tmp : rint(value_mul_tmp) / tmp;
3468 }
3469
3470 23215 double Item_func_round::real_op() {
3471 23215 const double value = args[0]->val_real();
3472 23215 const longlong decimal_places = args[1]->val_int();
3473
3474
6/6
✓ Branch 0 taken 23214 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 23213 times.
✓ Branch 4 taken 23213 times.
✓ Branch 5 taken 2 times.
23215 if (!(null_value = args[0]->null_value || args[1]->null_value))
3475 46426 return my_double_round(value, decimal_places, args[1]->unsigned_flag,
3476 23213 truncate);
3477
3478 2 return 0.0;
3479 }
3480
3481 /*
3482 Rounds a given value to a power of 10 specified as the 'to' argument.
3483 */
3484 123 static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to,
3485 bool *round_overflow) {
3486 123 ulonglong tmp = value / to * to;
3487
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 55 times.
123 if (value - tmp < (to >> 1)) {
3488 68 return tmp;
3489 } else {
3490
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 46 times.
55 if (test_if_sum_overflows_ull(tmp, to)) {
3491 9 *round_overflow = true;
3492 9 return 0;
3493 }
3494 46 return tmp + to;
3495 }
3496 }
3497
3498 178 longlong Item_func_round::int_op() {
3499 178 longlong value = args[0]->val_int();
3500 178 longlong dec = args[1]->val_int();
3501 178 decimals = 0;
3502 ulonglong abs_dec;
3503
3/6
✓ Branch 0 taken 178 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 178 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 178 times.
178 if ((null_value = args[0]->null_value || args[1]->null_value)) return 0;
3504
4/4
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 158 times.
178 if ((dec >= 0) || args[1]->unsigned_flag)
3505 20 return value; // integer have not digits after point
3506
3507 MY_COMPILER_DIAGNOSTIC_PUSH()
3508 // Suppress warning C4146 unary minus operator applied to unsigned type,
3509 // result still unsigned
3510 MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(4146)
3511 158 abs_dec = -static_cast<ulonglong>(dec);
3512 MY_COMPILER_DIAGNOSTIC_POP()
3513 longlong tmp;
3514
3515
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 148 times.
158 if (abs_dec >= array_elements(log_10_int)) return 0;
3516
3517 148 tmp = log_10_int[abs_dec];
3518
3519
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 143 times.
148 if (truncate)
3520
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 return (unsigned_flag) ? ((ulonglong)value / tmp) * tmp
3521 5 : (value / tmp) * tmp;
3522
4/4
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 59 times.
143 else if (unsigned_flag || value >= 0) {
3523 84 bool round_overflow = false;
3524 ulonglong rounded_value =
3525 84 my_unsigned_round(static_cast<ulonglong>(value), tmp, &round_overflow);
3526
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 14 times.
84 if (!unsigned_flag && rounded_value > LLONG_MAX)
3527
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 return raise_integer_overflow();
3528
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
74 if (round_overflow) return raise_integer_overflow();
3529 65 return rounded_value;
3530 } else {
3531 // We round "towards nearest", so
3532 // -9223372036854775808 should round to
3533 // -9223372036854775810 which underflows, or
3534 // -9223372036854775800 which is OK, or
3535 // -9223372036854776000 which underflows, and so on ...
3536
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 39 times.
59 if (value == LLONG_MIN) {
3537
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 9 times.
20 switch (abs_dec) {
3538 case 0:
3539 return LLONG_MIN;
3540 11 case 1:
3541 case 3:
3542 case 4:
3543 case 5:
3544 case 6:
3545 case 8:
3546 case 9:
3547 case 10:
3548 case 14:
3549 case 19:
3550
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 return raise_integer_overflow();
3551 9 default:
3552 9 return (LLONG_MIN / tmp) * tmp;
3553 }
3554 }
3555 39 bool not_used = false;
3556 ulonglong rounded_value =
3557 39 my_unsigned_round(static_cast<ulonglong>(-value), tmp, &not_used);
3558
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
39 if (rounded_value > LLONG_MAX) return raise_integer_overflow();
3559
3560 29 return -static_cast<longlong>(rounded_value);
3561 }
3562 }
3563
3564 4079 my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value) {
3565
1/2
✓ Branch 0 taken 4079 times.
✗ Branch 1 not taken.
4079 my_decimal val, *value = args[0]->val_decimal(&val);
3566
1/2
✓ Branch 0 taken 4079 times.
✗ Branch 1 not taken.
4079 longlong dec = args[1]->val_int();
3567
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 4040 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 35 times.
4079 if (dec >= 0 || args[1]->unsigned_flag)
3568 4044 dec = min<ulonglong>(dec, decimals);
3569
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 29 times.
35 else if (dec < INT_MIN)
3570 6 dec = INT_MIN;
3571
3572
6/6
✓ Branch 0 taken 3751 times.
✓ Branch 1 taken 328 times.
✓ Branch 2 taken 3750 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3750 times.
✓ Branch 5 taken 329 times.
7829 if (!(null_value = (args[0]->null_value || args[1]->null_value ||
3573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3750 times.
3750 my_decimal_round(E_DEC_FATAL_ERROR, value, (int)dec,
3574
1/2
✓ Branch 0 taken 3750 times.
✗ Branch 1 not taken.
3750 truncate, decimal_value) > 1)))
3575 3750 return decimal_value;
3576 329 return nullptr;
3577 4079 }
3578
3579 117970 bool Item_func_rand::itemize(Parse_context *pc, Item **res) {
3580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117971 times.
117970 if (skip_itemize(res)) return false;
3581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117970 times.
117971 if (super::itemize(pc, res)) return true;
3582 /*
3583 When RAND() is binlogged, the seed is binlogged too. So the
3584 sequence of random numbers is the same on a replication slave as
3585 on the master. However, if several RAND() values are inserted
3586 into a table, the order in which the rows are modified may differ
3587 between master and slave, because the order is undefined. Hence,
3588 the statement is unsafe to log in statement format.
3589 */
3590 117970 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
3591
3592 117971 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_RAND);
3593 117971 return false;
3594 }
3595
3596 40957 void Item_func_rand::seed_random(Item *arg) {
3597 /*
3598 TODO: do not do reinit 'rand' for every execute of PS/SP if
3599 args[0] is a constant.
3600 */
3601 40957 uint32 tmp = (uint32)arg->val_int();
3602 40957 randominit(m_rand, (uint32)(tmp * 0x10001L + 55555555L),
3603 (uint32)(tmp * 0x10000001L));
3604 40957 }
3605
3606 117264 bool Item_func_rand::resolve_type(THD *thd) {
3607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117264 times.
117264 if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_DOUBLE)) return true;
3608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117264 times.
117264 if (Item_real_func::resolve_type(thd)) return true;
3609 117264 return reject_geometry_args(arg_count, args, this);
3610 }
3611
3612 117265 bool Item_func_rand::fix_fields(THD *thd, Item **ref) {
3613
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 117263 times.
117265 if (Item_real_func::fix_fields(thd, ref)) return true;
3614
3615
2/2
✓ Branch 0 taken 40958 times.
✓ Branch 1 taken 76305 times.
117263 if (arg_count > 0) { // Only use argument once in query
3616 /*
3617 Allocate rand structure once: we must use thd->stmt_arena
3618 to create rand in proper mem_root if it's a prepared statement or
3619 stored procedure.
3620
3621 No need to send a Rand log event if seed was given eg: RAND(seed),
3622 as it will be replicated in the query as such.
3623 */
3624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40958 times.
40958 assert(m_rand == nullptr);
3625 40958 m_rand = pointer_cast<rand_struct *>(thd->alloc(sizeof(*m_rand)));
3626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40958 times.
40958 if (m_rand == nullptr) return true;
3627 } else {
3628 /*
3629 Save the seed only the first time RAND() is used in the query
3630 Once events are forwarded rather than recreated,
3631 the following can be skipped if inside the slave thread
3632 */
3633
2/2
✓ Branch 0 taken 69331 times.
✓ Branch 1 taken 6974 times.
76305 if (!thd->rand_used) {
3634 69331 thd->rand_used = true;
3635 69331 thd->rand_saved_seed1 = thd->rand.seed1;
3636 69331 thd->rand_saved_seed2 = thd->rand.seed2;
3637 }
3638 }
3639 117263 return false;
3640 }
3641
3642 2165988 double Item_func_rand::val_real() {
3643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2165988 times.
2165988 assert(fixed);
3644 rand_struct *rand;
3645
2/2
✓ Branch 0 taken 532124 times.
✓ Branch 1 taken 1633864 times.
2165988 if (arg_count > 0) {
3646
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 532108 times.
532124 if (!args[0]->const_for_execution())
3647 16 seed_random(args[0]);
3648
2/2
✓ Branch 0 taken 40941 times.
✓ Branch 1 taken 491167 times.
532108 else if (first_eval) {
3649 /*
3650 Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
3651 is a field item of "constant" table. Thus, we have to evaluate
3652 seed_random() for constant arg there but not at the fix_fields method.
3653 */
3654 40941 first_eval = false;
3655 40941 seed_random(args[0]);
3656 }
3657 532124 rand = m_rand;
3658 } else {
3659 /*
3660 Save the seed only the first time RAND() is used in the query
3661 Once events are forwarded rather than recreated,
3662 the following can be skipped if inside the slave thread
3663 */
3664 1633864 THD *const thd = current_thd;
3665
2/2
✓ Branch 0 taken 628822 times.
✓ Branch 1 taken 1005113 times.
1633935 if (!thd->rand_used) {
3666 628822 thd->rand_used = true;
3667 628822 thd->rand_saved_seed1 = thd->rand.seed1;
3668 628822 thd->rand_saved_seed2 = thd->rand.seed2;
3669 }
3670 1633935 rand = &thd->rand;
3671 }
3672 2166059 return my_rnd(rand);
3673 }
3674
3675 27 bool Item_func_sign::resolve_type(THD *thd) {
3676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true;
3677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (Item_int_func::resolve_type(thd)) return true;
3678 27 return reject_geometry_args(arg_count, args, this);
3679 }
3680
3681 34 longlong Item_func_sign::val_int() {
3682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(fixed == 1);
3683 34 double value = args[0]->val_real();
3684 34 null_value = args[0]->null_value;
3685
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 6 times.
34 return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
3686 }
3687
3688 37 bool Item_func_units::resolve_type(THD *thd) {
3689
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_DOUBLE)) return true;
3690 37 decimals = DECIMAL_NOT_SPECIFIED;
3691 37 max_length = float_length(decimals);
3692 37 return reject_geometry_args(arg_count, args, this);
3693 }
3694
3695 35 double Item_func_units::val_real() {
3696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 assert(fixed == 1);
3697 35 double value = args[0]->val_real();
3698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if ((null_value = args[0]->null_value)) return 0;
3699 35 return check_float_overflow(value * mul + add);
3700 }
3701
3702 3916 bool Item_func_min_max::resolve_type(THD *thd) {
3703 // If no arguments have type, type of this operator cannot be determined yet
3704
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3910 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 3910 times.
3922 if (args[0]->data_type() == MYSQL_TYPE_INVALID &&
3705 6 args[1]->data_type() == MYSQL_TYPE_INVALID)
3706 6 return false;
3707
3708
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3909 times.
3910 if (resolve_type_inner(thd)) return true;
3709 3909 return reject_geometry_args(arg_count, args, this);
3710 }
3711
3712 3916 bool Item_func_min_max::resolve_type_inner(THD *thd) {
3713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3916 times.
3916 if (param_type_uses_non_param(thd)) return true;
3714 3916 aggregate_type(make_array(args, arg_count));
3715 3916 hybrid_type = Field::result_merge_type(data_type());
3716
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 3692 times.
3916 if (hybrid_type == STRING_RESULT) {
3717 /*
3718 If one or more of the arguments have a temporal data type, temporal_item
3719 must be set for correct conversion from temporal values to various result
3720 types.
3721 */
3722
2/2
✓ Branch 0 taken 494 times.
✓ Branch 1 taken 224 times.
718 for (uint i = 0; i < arg_count; i++) {
3723
2/2
✓ Branch 0 taken 241 times.
✓ Branch 1 taken 253 times.
494 if (args[i]->is_temporal()) {
3724 /*
3725 If one of the arguments is DATETIME, overwrite any existing
3726 temporal_item since DATETIME contains both date and time and is the
3727 most general and detailed data type to which other temporal types can
3728 be converted without loss of information.
3729 */
3730
6/6
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 194 times.
✓ Branch 5 taken 47 times.
241 if (!temporal_item || args[i]->data_type() == MYSQL_TYPE_DATETIME)
3731 194 temporal_item = args[i];
3732 }
3733 }
3734 /*
3735 If one or more, but not all, of the arguments have a temporal data type,
3736 the data type of this item must be set temporarily to ensure that the
3737 various aggregate functions derive the correct properties.
3738 */
3739
2/2
✓ Branch 0 taken 103 times.
✓ Branch 1 taken 56 times.
383 enum_field_types tmp_data_type = (!is_temporal() && has_temporal_arg())
3740
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 65 times.
327 ? temporal_item->data_type()
3741 121 : data_type();
3742 224 enum_field_types aggregated_data_type = data_type();
3743 224 set_data_type(tmp_data_type);
3744
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 223 times.
224 if (aggregate_string_properties(func_name(), args, arg_count)) return true;
3745 223 set_data_type(aggregated_data_type);
3746 } else
3747 3692 aggregate_num_type(hybrid_type, args, arg_count);
3748
3749 /*
3750 LEAST and GREATEST convert JSON values to strings before they are
3751 compared, so their JSON nature is lost. Raise a warning to
3752 indicate to the users that the values are not compared using the
3753 JSON comparator, as they might expect. Also update the field type
3754 of the result to reflect that the result is a string.
3755 */
3756 3915 unsupported_json_comparison(arg_count, args,
3757 "comparison of JSON in the "
3758 "LEAST and GREATEST operators");
3759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3915 times.
3915 if (data_type() == MYSQL_TYPE_JSON) set_data_type(MYSQL_TYPE_VARCHAR);
3760 3915 return false;
3761 }
3762
3763 209 bool Item_func_min_max::cmp_datetimes(longlong *value) {
3764 209 THD *thd = current_thd;
3765 209 longlong res = 0;
3766
2/2
✓ Branch 0 taken 430 times.
✓ Branch 1 taken 192 times.
622 for (uint i = 0; i < arg_count; i++) {
3767 430 Item **arg = args + i;
3768 bool is_null;
3769 longlong tmp =
3770
1/2
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
430 get_datetime_value(thd, &arg, nullptr, temporal_item, &is_null);
3771
3772 // Check if we need to stop (because of error or KILL) and stop the loop
3773
3/4
✓ Branch 0 taken 430 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 429 times.
446 if ((null_value = thd->is_error())) return true;
3774
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 413 times.
429 if ((null_value = args[i]->null_value)) return true;
3775
4/4
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 192 times.
✓ Branch 2 taken 89 times.
✓ Branch 3 taken 132 times.
413 if (i == 0 || (tmp < res) == m_is_least_func) res = tmp;
3776 }
3777 192 *value = res;
3778 192 return false;
3779 }
3780
3781 10 bool Item_func_min_max::cmp_times(longlong *value) {
3782 10 longlong res = 0;
3783
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 8 times.
28 for (uint i = 0; i < arg_count; i++) {
3784 20 longlong tmp = args[i]->val_time_temporal();
3785
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if ((null_value = args[i]->null_value)) return true;
3786
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
18 if (i == 0 || (tmp < res) == m_is_least_func) res = tmp;
3787 }
3788 8 *value = res;
3789 8 return false;
3790 }
3791
3792 172 String *Item_func_min_max::str_op(String *str) {
3793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 172 times.
172 assert(fixed);
3794 172 null_value = false;
3795
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 72 times.
172 if (compare_as_dates()) {
3796 100 longlong result = 0;
3797
4/6
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
180 if (cmp_datetimes(&result)) return error_str();
3798
3799 /*
3800 If result is greater than 0, the winning argument was successfully
3801 converted to a time value and should be converted to a string
3802 formatted in accordance with the data type in temporal_item. Otherwise,
3803 the arguments should be compared based on their raw string value.
3804 */
3805
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 9 times.
89 if (result > 0) {
3806 MYSQL_TIME ltime;
3807 80 enum_field_types field_type = temporal_item->data_type();
3808
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 TIME_from_longlong_packed(&ltime, field_type, result);
3809
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 null_value = my_TIME_to_str(&ltime, str, decimals);
3810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (null_value) return nullptr;
3811
3/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 51 times.
80 if (str->needs_conversion(collation.collation)) {
3812 29 uint errors = 0;
3813 29 StringBuffer<STRING_BUFFER_USUAL_SIZE * 2> convert_string(nullptr);
3814 bool copy_failed =
3815
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 convert_string.copy(str->ptr(), str->length(), str->charset(),
3816 collation.collation, &errors);
3817
5/10
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 29 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 29 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 29 times.
29 if (copy_failed || errors || str->copy(convert_string))
3818 return error_str();
3819
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 }
3820 80 return str;
3821 }
3822 }
3823
3824 // Find the least/greatest argument based on string value.
3825 81 String *res = nullptr;
3826 81 bool res_in_str = false;
3827
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 71 times.
242 for (uint i = 0; i < arg_count; i++) {
3828 /*
3829 Because val_str() may reallocate the underlying buffer of its String
3830 parameter, it is paramount the passed String argument do not share an
3831 underlying buffer with the currently stored result against which it will
3832 be compared to ensure that String comparison operates on two
3833 non-overlapping buffers.
3834 */
3835
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 89 times.
171 String *val_buf = res_in_str ? &m_string_buf : str;
3836
4/6
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
171 assert(!res || (res != val_buf && !res->uses_buffer_owned_by(val_buf)));
3837 171 String *val = args[i]->val_str(val_buf);
3838
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 161 times.
171 if ((null_value = args[i]->null_value)) return nullptr;
3839
4/4
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 55 times.
246 if (i == 0 ||
3840
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 55 times.
85 (sortcmp(val, res, collation.collation) < 0) == m_is_least_func) {
3841 106 res = val;
3842 106 res_in_str = !res_in_str;
3843 }
3844 }
3845 71 res->set_charset(collation.collation);
3846 71 return res;
3847 }
3848
3849 85 bool Item_func_min_max::date_op(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) {
3850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 assert(fixed == 1);
3851 85 longlong result = 0;
3852
3/4
✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 80 times.
85 if (cmp_datetimes(&result)) return true;
3853
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 TIME_from_longlong_packed(ltime, data_type(), result);
3854 int warnings;
3855
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
80 return check_date(*ltime, non_zero_date(*ltime), fuzzydate, &warnings);
3856 }
3857
3858 10 bool Item_func_min_max::time_op(MYSQL_TIME *ltime) {
3859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 assert(fixed == 1);
3860 10 longlong result = 0;
3861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (compare_as_dates()) {
3862 if (cmp_datetimes(&result)) return true;
3863 TIME_from_longlong_packed(ltime, data_type(), result);
3864 datetime_to_time(ltime);
3865 return false;
3866 }
3867
3868
3/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
10 if (cmp_times(&result)) return true;
3869
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 TIME_from_longlong_time_packed(ltime, result);
3870 8 return false;
3871 }
3872
3873 27 double Item_func_min_max::real_op() {
3874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 assert(fixed == 1);
3875 27 null_value = false;
3876
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 13 times.
27 if (compare_as_dates()) {
3877 14 longlong result = 0;
3878
3/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
14 if (cmp_datetimes(&result)) return 0;
3879
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 return double_from_datetime_packed(temporal_item->data_type(), result);
3880 }
3881
3882 // Find the least/greatest argument based on double value.
3883 13 double result = 0.0;
3884
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 11 times.
38 for (uint i = 0; i < arg_count; i++) {
3885 27 const double tmp = args[i]->val_real();
3886
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 25 times.
27 if ((null_value = args[i]->null_value)) return 0.0;
3887
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
25 if (i == 0 || (tmp < result) == m_is_least_func) result = tmp;
3888 }
3889 11 return result;
3890 }
3891
3892 13772 longlong Item_func_min_max::int_op() {
3893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13772 times.
13772 assert(fixed);
3894 13772 null_value = false;
3895 13772 longlong res = 0;
3896
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13767 times.
13772 if (compare_as_dates()) {
3897
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (cmp_datetimes(&res)) return 0;
3898
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return longlong_from_datetime_packed(temporal_item->data_type(), res);
3899 }
3900
3901 // Find the least/greatest argument based on integer value.
3902
2/2
✓ Branch 0 taken 26129 times.
✓ Branch 1 taken 9410 times.
35539 for (uint i = 0; i < arg_count; i++) {
3903
1/2
✓ Branch 0 taken 26129 times.
✗ Branch 1 not taken.
26129 const longlong val = args[i]->val_int();
3904
2/2
✓ Branch 0 taken 4357 times.
✓ Branch 1 taken 21772 times.
26129 if ((null_value = args[i]->null_value)) return 0;
3905 #ifndef NDEBUG
3906 21772 Integer_value arg_val(val, args[i]->unsigned_flag);
3907
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 21756 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
21772 assert(!unsigned_flag || !arg_val.is_negative());
3908 #endif
3909
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 21756 times.
21772 const bool val_is_smaller = unsigned_flag ? static_cast<ulonglong>(val) <
3910 16 static_cast<ulonglong>(res)
3911 21756 : val < res;
3912
4/4
✓ Branch 0 taken 12358 times.
✓ Branch 1 taken 9414 times.
✓ Branch 2 taken 2921 times.
✓ Branch 3 taken 9437 times.
21772 if (i == 0 || val_is_smaller == m_is_least_func) res = val;
3913 }
3914 9410 return res;
3915 }
3916
3917 34 my_decimal *Item_func_min_max::decimal_op(my_decimal *dec) {
3918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 assert(fixed == 1);
3919 34 null_value = false;
3920
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 29 times.
34 if (compare_as_dates()) {
3921 5 longlong result = 0;
3922
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 if (cmp_datetimes(&result)) return nullptr;
3923
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 return my_decimal_from_datetime_packed(dec, temporal_item->data_type(),
3924 5 result);
3925 }
3926
3927 // Find the least/greatest argument based on decimal value.
3928
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 my_decimal tmp_buf, *res = args[0]->val_decimal(dec);
3929
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 28 times.
91 for (uint i = 0; i < arg_count; i++) {
3930
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
63 my_decimal *tmp = args[i]->val_decimal(res == dec ? &tmp_buf : dec);
3931
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 62 times.
63 if ((null_value = args[i]->null_value)) return nullptr;
3932
7/8
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✓ Branch 5 taken 16 times.
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 16 times.
62 if (i == 0 || (my_decimal_cmp(tmp, res) < 0) == m_is_least_func) res = tmp;
3933 }
3934 // Result must me copied from temporary buffer to remain valid after return.
3935
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 17 times.
28 if (res == &tmp_buf) {
3936
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 my_decimal2decimal(res, dec);
3937 11 res = dec;
3938 }
3939 28 return res;
3940 29 }
3941
3942 33 double Item_func_min_max::val_real() {
3943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 assert(fixed == 1);
3944
6/6
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 18 times.
✓ Branch 5 taken 15 times.
33 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3945 18 return real_op(); // For correct conversion from temporal value to string.
3946 15 return Item_func_numhybrid::val_real();
3947 }
3948
3949 13748 longlong Item_func_min_max::val_int() {
3950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13748 times.
13748 assert(fixed == 1);
3951
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 13743 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 13743 times.
13748 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3952 5 return int_op(); // For correct conversion from temporal value to int.
3953 13743 return Item_func_numhybrid::val_int();
3954 }
3955
3956 33 my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) {
3957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 assert(fixed == 1);
3958
6/6
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 28 times.
33 if (has_temporal_arg() && data_type() == MYSQL_TYPE_VARCHAR)
3959 5 return decimal_op(
3960 5 dec); // For correct conversion from temporal value to dec
3961 28 return Item_func_numhybrid::val_decimal(dec);
3962 }
3963
3964 13 bool Item_rollup_group_item::get_date(MYSQL_TIME *ltime,
3965 my_time_flags_t fuzzydate) {
3966
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 assert(fixed);
3967
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 if (rollup_null()) {
3968 2 null_value = true;
3969 2 return true;
3970 }
3971 11 return (null_value = args[0]->get_date(ltime, fuzzydate));
3972 }
3973
3974 5 bool Item_rollup_group_item::get_time(MYSQL_TIME *ltime) {
3975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(fixed);
3976
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (rollup_null()) {
3977 1 null_value = true;
3978 1 return true;
3979 }
3980 4 return (null_value = args[0]->get_time(ltime));
3981 }
3982
3983 323 double Item_rollup_group_item::val_real() {
3984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 323 times.
323 assert(fixed);
3985
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 255 times.
323 if (rollup_null()) {
3986 68 null_value = true;
3987 68 return 0.0;
3988 }
3989 255 double res = args[0]->val_real();
3990
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 240 times.
255 if ((null_value = args[0]->null_value)) return 0.0;
3991 240 return res;
3992 }
3993
3994 6319 longlong Item_rollup_group_item::val_int() {
3995
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6319 times.
6319 assert(fixed);
3996
2/2
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 5418 times.
6319 if (rollup_null()) {
3997 901 null_value = true;
3998 901 return 0;
3999 }
4000 5418 longlong res = args[0]->val_int();
4001
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 5322 times.
5418 if ((null_value = args[0]->null_value)) return 0;
4002 5322 return res;
4003 }
4004
4005 1061 String *Item_rollup_group_item::val_str(String *str) {
4006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1061 times.
1061 assert(fixed);
4007
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 923 times.
1061 if (rollup_null()) {
4008 138 null_value = true;
4009 138 return nullptr;
4010 }
4011 923 String *res = args[0]->val_str(str);
4012
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 914 times.
923 if ((null_value = args[0]->null_value)) return nullptr;
4013 914 return res;
4014 }
4015
4016 212 my_decimal *Item_rollup_group_item::val_decimal(my_decimal *dec) {
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 assert(fixed);
4018
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 207 times.
212 if (rollup_null()) {
4019 5 null_value = true;
4020 5 return nullptr;
4021 }
4022 207 my_decimal *res = args[0]->val_decimal(dec);
4023
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 168 times.
207 if ((null_value = args[0]->null_value)) return nullptr;
4024 168 return res;
4025 }
4026
4027 5 bool Item_rollup_group_item::val_json(Json_wrapper *result) {
4028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(fixed);
4029
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (rollup_null()) {
4030 1 null_value = true;
4031 1 return false;
4032 }
4033 4 bool res = args[0]->val_json(result);
4034 4 null_value = args[0]->null_value;
4035 4 return res;
4036 }
4037
4038 110 void Item_rollup_group_item::print(const THD *thd, String *str,
4039 enum_query_type query_type) const {
4040
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 106 times.
110 if (query_type & QT_HIDE_ROLLUP_FUNCTIONS) {
4041
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 print_args(thd, str, 0, query_type);
4042 4 return;
4043 }
4044
4045
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 str->append(func_name());
4046
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 str->append('(');
4047
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 print_args(thd, str, 0, query_type);
4048
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 str->append(',');
4049 char buf[16];
4050 106 snprintf(buf, sizeof(buf), "%d", m_min_rollup_level);
4051
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 str->append(buf);
4052
1/2
✓ Branch 0 taken 106 times.
✗ Branch 1 not taken.
106 str->append(')');
4053 }
4054
4055 209 bool Item_rollup_group_item::eq(const Item *item, bool binary_cmp) const {
4056
4/4
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 1 times.
336 return Item_func::eq(item, binary_cmp) &&
4057 127 min_rollup_level() == down_cast<const Item_rollup_group_item *>(item)
4058 336 ->min_rollup_level();
4059 }
4060
4061 19332052 longlong Item_func_length::val_int() {
4062
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19332052 times.
19332052 assert(fixed == 1);
4063 19332052 String *res = args[0]->val_str(&value);
4064
2/2
✓ Branch 0 taken 16201693 times.
✓ Branch 1 taken 3130359 times.
19332052 if (!res) {
4065 16201693 null_value = true;
4066 16201693 return 0; /* purecov: inspected */
4067 }
4068 3130359 null_value = false;
4069 3130359 return (longlong)res->length();
4070 }
4071
4072 780301 longlong Item_func_char_length::val_int() {
4073
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 780301 times.
780301 assert(fixed == 1);
4074 780301 String *res = args[0]->val_str(&value);
4075
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 780218 times.
780301 if (!res) {
4076 83 null_value = true;
4077 83 return 0; /* purecov: inspected */
4078 }
4079 780218 null_value = false;
4080 780218 return (longlong)res->numchars();
4081 }
4082
4083 114 longlong Item_func_coercibility::val_int() {
4084
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 assert(fixed == 1);
4085 114 null_value = false;
4086 114 return (longlong)args[0]->collation.derivation;
4087 }
4088
4089 445723 bool Item_func_locate::resolve_type(THD *thd) {
4090
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 445723 times.
445723 if (param_type_is_default(thd, 0, 2)) return true;
4091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 445723 times.
445723 if (param_type_is_default(thd, 2, 3, MYSQL_TYPE_LONGLONG)) return true;
4092 445723 max_length = MY_INT32_NUM_DECIMAL_DIGITS;
4093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 445723 times.
445723 if (agg_arg_charsets_for_string_result(collation, args, 1)) return true;
4094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 445723 times.
445723 if (simplify_string_args(thd, collation, args + 1, 1)) return true;
4095 445723 return false;
4096 }
4097
4098 693944 longlong Item_func_locate::val_int() {
4099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 693944 times.
693944 assert(fixed);
4100 // Evaluate the string argument first
4101 693944 const CHARSET_INFO *cs = collation.collation;
4102
1/2
✓ Branch 0 taken 693944 times.
✗ Branch 1 not taken.
693944 String *a = eval_string_arg(cs, args[0], &value1);
4103
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 693795 times.
693944 if (a == nullptr) return error_int();
4104
4105 // Evaluate substring argument in same character set as string argument
4106
1/2
✓ Branch 0 taken 693795 times.
✗ Branch 1 not taken.
693795 String *b = eval_string_arg(cs, args[1], &value2);
4107
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 693740 times.
693795 if (b == nullptr) return error_int();
4108
4109 693740 null_value = false;
4110 /* must be longlong to avoid truncation */
4111 693740 longlong start = 0;
4112 693740 longlong start0 = 0;
4113 my_match_t match;
4114
4115
2/2
✓ Branch 0 taken 31259 times.
✓ Branch 1 taken 662481 times.
693740 if (arg_count == 3) {
4116
1/2
✓ Branch 0 taken 31259 times.
✗ Branch 1 not taken.
31259 const longlong tmp = args[2]->val_int();
4117
6/6
✓ Branch 0 taken 31240 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 31178 times.
✓ Branch 4 taken 81 times.
✓ Branch 5 taken 31178 times.
31259 if ((null_value = args[2]->null_value) || tmp <= 0) return 0;
4118 31178 start0 = start = tmp - 1;
4119
4120
2/2
✓ Branch 0 taken 431 times.
✓ Branch 1 taken 30747 times.
31178 if (start > static_cast<longlong>(a->length())) return 0;
4121
4122 /* start is now sufficiently valid to pass to charpos function */
4123
1/2
✓ Branch 0 taken 30747 times.
✗ Branch 1 not taken.
30747 start = a->charpos((int)start);
4124
4125
2/2
✓ Branch 0 taken 728 times.
✓ Branch 1 taken 30019 times.
30747 if (start + b->length() > a->length()) return 0;
4126 }
4127
4128
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 692454 times.
692500 if (!b->length()) // Found empty string at start
4129 46 return start + 1;
4130
4131
3/4
✓ Branch 0 taken 692454 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 310648 times.
✓ Branch 3 taken 381806 times.
1384908 if (!cs->coll->strstr(cs, a->ptr() + start,
4132 692454 static_cast<uint>(a->length() - start), b->ptr(),
4133 b->length(), &match, 1))
4134 310648 return 0;
4135 381806 return static_cast<longlong>(match.mb_len) + start0 + 1;
4136 }
4137
4138 41408 void Item_func_locate::print(const THD *thd, String *str,
4139 enum_query_type query_type) const {
4140 41408 str->append(STRING_WITH_LEN("locate("));
4141 41408 args[1]->print(thd, str, query_type);
4142 41408 str->append(',');
4143 41408 args[0]->print(thd, str, query_type);
4144
2/2
✓ Branch 0 taken 981 times.
✓ Branch 1 taken 40427 times.
41408 if (arg_count == 3) {
4145 981 str->append(',');
4146 981 args[2]->print(thd, str, query_type);
4147 }
4148 41408 str->append(')');
4149 41408 }
4150
4151 43 longlong Item_func_validate_password_strength::val_int() {
4152 char buff[STRING_BUFFER_USUAL_SIZE];
4153 43 String value(buff, sizeof(buff), system_charset_info);
4154
1/2
✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
43 String *field = args[0]->val_str(&value);
4155
6/6
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 38 times.
43 if ((null_value = args[0]->null_value) || field->length() == 0) return 0;
4156
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 return (my_calculate_password_strength(field->ptr(), field->length()));
4157 43 }
4158
4159 133 longlong Item_func_field::val_int() {
4160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 assert(fixed);
4161
4162
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 22 times.
133 if (cmp_type == STRING_RESULT) {
4163 111 const CHARSET_INFO *cs = collation.collation;
4164 111 String *field = eval_string_arg(cs, args[0], &value);
4165
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 106 times.
111 if (field == nullptr) return 0;
4166
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 7 times.
206 for (uint i = 1; i < arg_count; i++) {
4167 199 String *tmp_value = eval_string_arg(cs, args[i], &tmp);
4168
6/6
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 95 times.
✓ Branch 4 taken 99 times.
✓ Branch 5 taken 100 times.
199 if (tmp_value != nullptr && !sortcmp(field, tmp_value, cs)) {
4169 99 return i;
4170 }
4171 }
4172
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 16 times.
22 } else if (cmp_type == INT_RESULT) {
4173 6 longlong val = args[0]->val_int();
4174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (args[0]->null_value) return 0;
4175
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for (uint i = 1; i < arg_count; i++) {
4176
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 5 times.
6 if (val == args[i]->val_int() && !args[i]->null_value) {
4177 1 return i;
4178 }
4179 }
4180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 } else if (cmp_type == DECIMAL_RESULT) {
4181 my_decimal dec_arg_buf, *dec_arg, dec_buf,
4182 *dec = args[0]->val_decimal(&dec_buf);
4183 if (args[0]->null_value) return 0;
4184 for (uint i = 1; i < arg_count; i++) {
4185 dec_arg = args[i]->val_decimal(&dec_arg_buf);
4186 if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec)) {
4187 return i;
4188 }
4189 }
4190 } else {
4191 16 double val = args[0]->val_real();
4192
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11 times.
16 if (args[0]->null_value) return 0;
4193
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 for (uint i = 1; i < arg_count; i++) {
4194
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 19 times.
24 if (val == args[i]->val_real() && !args[i]->null_value) {
4195 5 return i;
4196 }
4197 }
4198 }
4199 18 return 0;
4200 }
4201
4202 73 bool Item_func_field::resolve_type(THD *thd) {
4203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 if (Item_int_func::resolve_type(thd)) return true;
4204 73 set_nullable(false);
4205 73 max_length = 3;
4206 73 cmp_type = args[0]->result_type();
4207
2/2
✓ Branch 0 taken 257 times.
✓ Branch 1 taken 73 times.
330 for (uint i = 1; i < arg_count; i++)
4208 257 cmp_type = item_cmp_type(cmp_type, args[i]->result_type());
4209
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 17 times.
73 if (cmp_type == STRING_RESULT) {
4210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (agg_arg_charsets_for_string_result(collation, args, 1)) return true;
4211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 if (simplify_string_args(thd, collation, args + 1, arg_count - 1))
4212 return true;
4213 }
4214 73 return false;
4215 }
4216
4217 52054 longlong Item_func_ascii::val_int() {
4218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52054 times.
52054 assert(fixed == 1);
4219 52054 String *res = args[0]->val_str(&value);
4220
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52052 times.
52054 if (!res) {
4221 2 null_value = true;
4222 2 return 0;
4223 }
4224 52052 null_value = false;
4225
2/2
✓ Branch 0 taken 52050 times.
✓ Branch 1 taken 2 times.
52052 return (longlong)(res->length() ? (uchar)(*res)[0] : (uchar)0);
4226 }
4227
4228 656429 longlong Item_func_ord::val_int() {
4229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 assert(fixed == 1);
4230 656429 String *res = args[0]->val_str(&value);
4231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 if (!res) {
4232 null_value = true;
4233 return 0;
4234 }
4235 656429 null_value = false;
4236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 656429 times.
656429 if (!res->length()) return 0;
4237
2/2
✓ Branch 0 taken 611942 times.
✓ Branch 1 taken 44487 times.
656429 if (use_mb(res->charset())) {
4238 611942 const char *str = res->ptr();
4239 611942 uint32 n = 0, l = my_ismbchar(res->charset(), str, str + res->length());
4240
2/2
✓ Branch 0 taken 17046 times.
✓ Branch 1 taken 594896 times.
611942 if (!l) return (longlong)((uchar)*str);
4241
2/2
✓ Branch 0 taken 1251290 times.
✓ Branch 1 taken 594896 times.
1846186 while (l--) n = (n << 8) | (uint32)((uchar)*str++);
4242 594896 return (longlong)n;
4243 }
4244 44487 return (longlong)((uchar)(*res)[0]);
4245 }
4246
4247 /* Search after a string in a string of strings separated by ',' */
4248 /* Returns number of found type >= 1 or 0 if not found */
4249 /* This optimizes searching in enums to bit testing! */
4250
4251 4356 bool Item_func_find_in_set::resolve_type(THD *thd) {
4252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4356 times.
4356 if (param_type_is_default(thd, 0, -1)) return true;
4253 4356 max_length = 3; // 1-999
4254
4255
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4354 times.
4356 if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) {
4256 2 return true;
4257 }
4258
6/6
✓ Branch 0 taken 4078 times.
✓ Branch 1 taken 276 times.
✓ Branch 2 taken 3192 times.
✓ Branch 3 taken 886 times.
✓ Branch 4 taken 3190 times.
✓ Branch 5 taken 1164 times.
7546 if (args[0]->const_item() && args[1]->type() == FIELD_ITEM &&
4259
2/2
✓ Branch 0 taken 3190 times.
✓ Branch 1 taken 2 times.
3192 args[0]->may_eval_const_item(thd)) {
4260 3190 Field *field = down_cast<Item_field *>(args[1])->field;
4261
2/2
✓ Branch 0 taken 3185 times.
✓ Branch 1 taken 5 times.
3190 if (field->real_type() == MYSQL_TYPE_SET) {
4262 3185 String *find = args[0]->val_str(&value);
4263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3185 times.
3185 if (thd->is_error()) return true;
4264
2/2
✓ Branch 0 taken 3183 times.
✓ Branch 1 taken 2 times.
3185 if (find != nullptr) {
4265 // find is not NULL pointer so args[0] is not a null-value
4266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3183 times.
3183 assert(!args[0]->null_value);
4267 6366 m_enum_value = find_type(down_cast<Field_enum *>(field)->typelib,
4268 3183 find->ptr(), find->length(), false);
4269 }
4270 }
4271 }
4272 4354 return false;
4273 }
4274
4275 static const char separator = ',';
4276
4277 4529 longlong Item_func_find_in_set::val_int() {
4278
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4529 times.
4529 assert(fixed);
4279
4280 4529 null_value = false;
4281
4282
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 4149 times.
4529 if (m_enum_value != 0) {
4283 // enum_value is set iff args[0]->const_item() in resolve_type().
4284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 380 times.
380 assert(args[0]->const_item());
4285
4286 380 ulonglong tmp = static_cast<ulonglong>(args[1]->val_int());
4287
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 379 times.
380 if (args[1]->null_value) return error_int();
4288 /*
4289 No need to check args[0]->null_value since enum_value is set iff
4290 args[0] is a non-null const item. Note: no assert on
4291 args[0]->null_value here because args[0] may have been replaced
4292 by an Item_cache on which val_int() has not been called. See
4293 BUG#11766317
4294 */
4295
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 309 times.
379 return (tmp & (1ULL << (m_enum_value - 1))) ? m_enum_value : 0;
4296 }
4297
4298 4149 String *find = args[0]->val_str(&value);
4299
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4129 times.
4149 if (find == nullptr) return error_int();
4300
4301
4/4
✓ Branch 0 taken 551 times.
✓ Branch 1 taken 3578 times.
✓ Branch 2 taken 55 times.
✓ Branch 3 taken 4074 times.
4680 if (args[1]->type() == FIELD_ITEM &&
4302
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 496 times.
551 down_cast<Item_field *>(args[1])->field->real_type() == MYSQL_TYPE_SET) {
4303 55 Field *field = down_cast<Item_field *>(args[1])->field;
4304
4305 55 ulonglong tmp = static_cast<ulonglong>(args[1]->val_int());
4306
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52 times.
55 if (args[1]->null_value) return error_int();
4307
4308 52 uint value = find_type(down_cast<Field_enum *>(field)->typelib, find->ptr(),
4309 find->length(), false);
4310
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
52 return (value != 0 && (tmp & (1ULL << (value - 1)))) ? value : 0;
4311 }
4312
4313 4074 String *buffer = args[1]->val_str(&value2);
4314
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4072 times.
4074 if (buffer == nullptr) return error_int();
4315
4316
2/2
✓ Branch 0 taken 3814 times.
✓ Branch 1 taken 258 times.
4072 if (buffer->length() >= find->length()) {
4317 3814 my_wc_t wc = 0;
4318 3814 const CHARSET_INFO *cs = cmp_collation.collation;
4319 3814 const char *str_begin = buffer->ptr();
4320 3814 const char *str_end = buffer->ptr();
4321 3814 const char *real_end = str_end + buffer->length();
4322 3814 const uchar *find_str = (const uchar *)find->ptr();
4323 3814 size_t find_str_len = find->length();
4324 3814 int position = 0;
4325 while (true) {
4326 int symbol_len;
4327 64005 if ((symbol_len =
4328
1/2
✓ Branch 0 taken 64005 times.
✗ Branch 1 not taken.
64005 cs->cset->mb_wc(cs, &wc, pointer_cast<const uchar *>(str_end),
4329
2/2
✓ Branch 0 taken 61319 times.
✓ Branch 1 taken 2686 times.
64005 pointer_cast<const uchar *>(real_end))) > 0) {
4330 61319 const char *substr_end = str_end + symbol_len;
4331 61319 bool is_last_item = (substr_end == real_end);
4332 61319 bool is_separator = (wc == (my_wc_t)separator);
4333
4/4
✓ Branch 0 taken 58940 times.
✓ Branch 1 taken 2379 times.
✓ Branch 2 taken 3201 times.
✓ Branch 3 taken 55739 times.
61319 if (is_separator || is_last_item) {
4334 5580 position++;
4335
4/4
✓ Branch 0 taken 3341 times.
✓ Branch 1 taken 2239 times.
✓ Branch 2 taken 3201 times.
✓ Branch 3 taken 140 times.
5580 if (is_last_item && !is_separator) str_end = substr_end;
4336
3/4
✓ Branch 0 taken 5580 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1128 times.
✓ Branch 3 taken 4452 times.
5580 if (!my_strnncoll(cs, (const uchar *)str_begin,
4337 (uint)(str_end - str_begin), find_str,
4338 find_str_len))
4339 1128 return (longlong)position;
4340 else
4341 4452 str_begin = substr_end;
4342 }
4343 60191 str_end = substr_end;
4344
3/4
✓ Branch 0 taken 2686 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1834 times.
✓ Branch 3 taken 852 times.
2686 } else if (str_end - str_begin == 0 && find_str_len == 0 &&
4345
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1833 times.
1834 wc == (my_wc_t)separator) {
4346 1 return ++position;
4347 } else {
4348 2685 return 0;
4349 }
4350 60191 }
4351 }
4352 258 return 0;
4353 }
4354
4355 487 longlong Item_func_bit_count::val_int() {
4356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 487 times.
487 assert(fixed);
4357
2/2
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 25 times.
487 if (bit_func_returns_binary(args[0], nullptr)) {
4358 462 String *s = args[0]->val_str(&str_value);
4359
2/4
✓ Branch 0 taken 462 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 462 times.
462 if (args[0]->null_value || !s) return error_int();
4360
4361 462 const char *val = s->ptr();
4362
4363 462 longlong len = 0;
4364 462 size_t i = 0;
4365 462 size_t arg_length = s->length();
4366
2/2
✓ Branch 0 taken 530 times.
✓ Branch 1 taken 462 times.
992 while (i + sizeof(longlong) <= arg_length) {
4367 530 len += my_count_bits(uint8korr(&val[i]));
4368 530 i += sizeof(longlong);
4369 }
4370
2/2
✓ Branch 0 taken 513 times.
✓ Branch 1 taken 462 times.
975 while (i < arg_length) {
4371 513 len += _my_bits_nbits[(uchar)val[i]];
4372 513 i++;
4373 }
4374
4375 462 null_value = false;
4376 462 return len;
4377 }
4378
4379 25 ulonglong value = (ulonglong)args[0]->val_int();
4380
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24 times.
25 if (args[0]->null_value) return error_int(); /* purecov: inspected */
4381
4382 24 null_value = false;
4383 24 return (longlong)my_count_bits(value);
4384 }
4385
4386 /****************************************************************************
4387 ** Functions to handle dynamic loadable functions
4388 ****************************************************************************/
4389
4390 23226 udf_handler::udf_handler(udf_func *udf_arg)
4391 23226 : u_d(udf_arg),
4392 23226 m_args_extension(),
4393 23226 m_return_value_extension(&my_charset_bin, result_type()) {}
4394
4395 23206 void udf_handler::cleanup() {
4396
4/4
✓ Branch 0 taken 23199 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1358 times.
✓ Branch 3 taken 21841 times.
23206 if (!m_original || !m_initialized) return;
4397
4398 21841 clean_buffers();
4399 /*
4400 Make sure to not free the handler from the cleanup() call when
4401 (re)preparing the UDF function call. The handler allocated by
4402 udf_handler::fix_fields() will be used in execution.
4403 */
4404 21841 THD *thd = current_thd;
4405
6/6
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 21757 times.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 37 times.
✓ Branch 4 taken 47 times.
✓ Branch 5 taken 21794 times.
21842 if (thd->stmt_arena->is_stmt_prepare() && thd->stmt_arena->is_repreparing)
4406 47 return;
4407
4408
4/4
✓ Branch 0 taken 21425 times.
✓ Branch 1 taken 369 times.
✓ Branch 2 taken 20762 times.
✓ Branch 3 taken 663 times.
21794 if (m_init_func_called && u_d->func_deinit != nullptr) {
4409 20762 (*u_d->func_deinit)(&initid);
4410 20762 m_init_func_called = false;
4411 }
4412
1/2
✓ Branch 0 taken 21794 times.
✗ Branch 1 not taken.
21794 DEBUG_SYNC(current_thd, "udf_handler_destroy_sync");
4413 21795 free_handler();
4414 }
4415
4416 23151 void udf_handler::clean_buffers() {
4417
2/2
✓ Branch 0 taken 10201 times.
✓ Branch 1 taken 12950 times.
23151 if (buffers == nullptr) return;
4418
2/2
✓ Branch 0 taken 30508 times.
✓ Branch 1 taken 12950 times.
43458 for (uint i = 0; i < f_args.arg_count; i++) {
4419 30508 buffers[i].mem_free();
4420 }
4421 }
4422
4423 23106 void udf_handler::free_handler() {
4424 // deinit() should have been called by cleanup()
4425
3/6
✓ Branch 0 taken 23106 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23106 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23106 times.
✗ Branch 5 not taken.
23106 assert(m_original && m_initialized && u_d != nullptr);
4426 23106 free_udf(u_d);
4427 23106 u_d = nullptr;
4428 23106 m_initialized = false;
4429 23106 }
4430
4431 23066 bool Item_udf_func::fix_fields(THD *thd, Item **) {
4432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23066 times.
23066 assert(fixed == 0);
4433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23069 times.
23066 assert(!thd->is_error());
4434
2/2
✓ Branch 0 taken 1308 times.
✓ Branch 1 taken 21761 times.
23069 if (udf.fix_fields(thd, this, arg_count, args)) return true;
4435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21761 times.
21761 if (thd->is_error()) return true;
4436 21761 used_tables_cache = udf.used_tables_cache;
4437 21761 fixed = true;
4438 21761 return false;
4439 }
4440
4441 23104 bool udf_handler::fix_fields(THD *thd, Item_result_field *func, uint arg_count,
4442 Item **arguments) {
4443 uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
4444
1/2
✓ Branch 0 taken 23105 times.
✗ Branch 1 not taken.
23104 DBUG_TRACE;
4445
4446
2/4
✓ Branch 0 taken 23106 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23106 times.
23105 if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
4447 return true; // Fatal error flag is set!
4448
4449
1/2
✓ Branch 0 taken 23106 times.
✗ Branch 1 not taken.
23106 udf_func *tmp_udf = find_udf(u_d->name.str, (uint)u_d->name.length, true);
4450
4451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23106 times.
23106 if (!tmp_udf) {
4452 my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str);
4453 return true;
4454 }
4455 23106 u_d = tmp_udf;
4456 23106 args = arguments;
4457
4458 23106 m_initialized = true; // Use count was incremented by find_udf()
4459 /*
4460 RAII wrapper to free the memory allocated in case of any failure while
4461 initializing the UDF
4462 */
4463 class cleanup_guard {
4464 public:
4465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23106 times.
23106 cleanup_guard(udf_handler *udf) : m_udf(udf) { assert(udf); }
4466 24417 ~cleanup_guard() {
4467
2/2
✓ Branch 0 taken 21795 times.
✓ Branch 1 taken 1311 times.
23106 if (m_udf == nullptr) return;
4468 1311 m_udf->clean_buffers();
4469 1311 m_udf->free_handler();
4470 23106 }
4471 21795 void defer() { m_udf = nullptr; }
4472
4473 private:
4474 udf_handler *m_udf;
4475 23106 } udf_fun_guard(this);
4476
4477 /* Fix all arguments */
4478 23106 func->set_nullable(false);
4479 23106 used_tables_cache = 0;
4480
4481
2/2
✓ Branch 0 taken 12910 times.
✓ Branch 1 taken 10196 times.
23106 if ((f_args.arg_count = arg_count)) {
4482 12910 if (!(f_args.arg_type =
4483
1/2
✓ Branch 0 taken 12910 times.
✗ Branch 1 not taken.
12910 (Item_result *)(*THR_MALLOC)
4484
2/4
✓ Branch 0 taken 12910 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12910 times.
12910 ->Alloc(f_args.arg_count * sizeof(Item_result)))) {
4485 return true;
4486 }
4487 uint i;
4488 Item **arg, **arg_end;
4489 12910 for (i = 0, arg = arguments, arg_end = arguments + arg_count;
4490
2/2
✓ Branch 0 taken 30410 times.
✓ Branch 1 taken 12907 times.
43317 arg != arg_end; arg++, i++) {
4491
7/8
✓ Branch 0 taken 17739 times.
✓ Branch 1 taken 12671 times.
✓ Branch 2 taken 17739 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17738 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 30409 times.
30410 if (!(*arg)->fixed && (*arg)->fix_fields(thd, arg)) {
4492 1 return true;
4493 }
4494 // we can't assign 'item' before, because fix_fields() can change arg
4495 30409 Item *item = *arg;
4496
3/4
✓ Branch 0 taken 30409 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 30407 times.
30409 if (item->check_cols(1)) {
4497 2 return true;
4498 }
4499 /*
4500 TODO: We should think about this. It is not always
4501 right way just to set an UDF result to return my_charset_bin
4502 if one argument has binary sorting order.
4503 The result collation should be calculated according to arguments
4504 derivations in some cases and should not in other cases.
4505 Moreover, some arguments can represent a numeric input
4506 which doesn't effect the result character set and collation.
4507 There is no a general rule for UDF. Everything depends on
4508 the particular user defined function.
4509 */
4510
2/2
✓ Branch 0 taken 7789 times.
✓ Branch 1 taken 22618 times.
30407 if (item->collation.collation->state & MY_CS_BINSORT)
4511 7789 func->collation.set(&my_charset_bin);
4512 30407 func->m_nullable |= item->m_nullable;
4513 30407 func->add_accum_properties(item);
4514
1/2
✓ Branch 0 taken 30407 times.
✗ Branch 1 not taken.
30407 used_tables_cache |= item->used_tables();
4515
1/2
✓ Branch 0 taken 30407 times.
✗ Branch 1 not taken.
30407 f_args.arg_type[i] = item->result_type();
4516 }
4517 // TODO: why all following memory is not allocated with 1 call of sql_alloc?
4518 // if (!(buffers = new String[arg_count]) ||
4519 12907 if (!(buffers = pointer_cast<String *>(
4520
2/4
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
12907 (*THR_MALLOC)->Alloc(sizeof(String) * arg_count))) ||
4521 12907 !(f_args.args =
4522
3/6
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12907 times.
✗ Branch 5 not taken.
12907 (char **)(*THR_MALLOC)->Alloc(arg_count * sizeof(char *))) ||
4523 12907 !(f_args.lengths =
4524
3/6
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12907 times.
✗ Branch 5 not taken.
12907 (ulong *)(*THR_MALLOC)->Alloc(arg_count * sizeof(long))) ||
4525 12907 !(f_args.maybe_null =
4526
3/6
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12907 times.
✗ Branch 5 not taken.
12907 (char *)(*THR_MALLOC)->Alloc(arg_count * sizeof(char))) ||
4527
1/2
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
12907 !(num_buffer = (char *)(*THR_MALLOC)
4528
2/4
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
12907 ->Alloc(arg_count * ALIGN_SIZE(sizeof(double)))) ||
4529 12907 !(f_args.attributes =
4530
3/6
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12907 times.
✗ Branch 5 not taken.
12907 (char **)(*THR_MALLOC)->Alloc(arg_count * sizeof(char *))) ||
4531 12907 !(f_args.attribute_lengths =
4532
5/10
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12907 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12907 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12907 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 12907 times.
38721 (ulong *)(*THR_MALLOC)->Alloc(arg_count * sizeof(long))) ||
4533 12907 !(m_args_extension.charset_info =
4534
1/2
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
12907 (const CHARSET_INFO **)(*THR_MALLOC)
4535
2/4
✓ Branch 0 taken 12907 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12907 times.
12907 ->Alloc(f_args.arg_count * sizeof(CHARSET_INFO *)))) {
4536 return true;
4537 }
4538 }
4539
2/2
✓ Branch 0 taken 30406 times.
✓ Branch 1 taken 23103 times.
53509 for (uint i = 0; i < arg_count; i++) {
4540 30406 (void)::new (buffers + i) String;
4541 30406 m_args_extension.charset_info[i] = nullptr;
4542 }
4543
4544
2/4
✓ Branch 0 taken 23103 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 23103 times.
23103 if (func->resolve_type(thd)) return true;
4545
4546 23103 initid.max_length = func->max_length;
4547 23103 initid.maybe_null = func->m_nullable;
4548 23103 initid.const_item = used_tables_cache == 0;
4549 23103 initid.decimals = func->decimals;
4550 23103 initid.ptr = nullptr;
4551 23103 initid.extension = &m_return_value_extension;
4552
4553
6/6
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 23019 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 23072 times.
23140 if (thd->stmt_arena->is_stmt_prepare() && !thd->stmt_arena->is_repreparing &&
4554
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 6 times.
37 !initid.const_item) {
4555 31 udf_fun_guard.defer();
4556 31 return false;
4557 }
4558
2/2
✓ Branch 0 taken 22733 times.
✓ Branch 1 taken 339 times.
23072 if (u_d->func_init) {
4559
3/4
✓ Branch 0 taken 22732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1308 times.
✓ Branch 3 taken 21424 times.
22733 if (call_init_func()) {
4560 1308 return true;
4561 }
4562 21424 func->max_length = min<uint32>(initid.max_length, MAX_BLOB_WIDTH);
4563 21424 func->m_nullable = initid.maybe_null;
4564
4/4
✓ Branch 0 taken 8666 times.
✓ Branch 1 taken 12758 times.
✓ Branch 2 taken 3747 times.
✓ Branch 3 taken 4919 times.
21424 if (!initid.const_item && used_tables_cache == 0)
4565 3747 used_tables_cache = RAND_TABLE_BIT;
4566 21424 func->decimals = min<uint>(initid.decimals, DECIMAL_NOT_SPECIFIED);
4567 /*
4568 For UDFs of type string, override character set and collation from
4569 return value extension specification.
4570 */
4571
2/2
✓ Branch 0 taken 16977 times.
✓ Branch 1 taken 4448 times.
21424 if (result_type() == STRING_RESULT)
4572 16977 func->set_data_type_string(func->max_length,
4573 m_return_value_extension.charset_info);
4574 }
4575 /*
4576 UDF initialization complete so leave the freeing up resources to
4577 cleanup method.
4578 */
4579 21764 udf_fun_guard.defer();
4580 21764 return false;
4581 23106 }
4582
4583 22733 bool udf_handler::call_init_func() {
4584 char init_msg_buff[MYSQL_ERRMSG_SIZE];
4585 22733 *init_msg_buff = '\0';
4586 22733 char *to = num_buffer;
4587 22733 f_args.extension = &m_args_extension;
4588
4589
2/2
✓ Branch 0 taken 30299 times.
✓ Branch 1 taken 22734 times.
53033 for (uint i = 0; i < f_args.arg_count; i++) {
4590 /*
4591 For a constant argument i, args->args[i] points to the argument value.
4592 For non-constant, args->args[i] is NULL.
4593 */
4594 30299 f_args.args[i] = nullptr; // Non-const unless updated below
4595
4596 30299 f_args.lengths[i] = args[i]->max_length;
4597 30299 f_args.maybe_null[i] = args[i]->m_nullable;
4598 30299 f_args.attributes[i] = const_cast<char *>(args[i]->item_name.ptr());
4599 30300 f_args.attribute_lengths[i] = args[i]->item_name.length();
4600 30300 m_args_extension.charset_info[i] = args[i]->collation.collation;
4601
4602
6/8
✓ Branch 0 taken 30300 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29971 times.
✓ Branch 3 taken 329 times.
✓ Branch 4 taken 29971 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 29971 times.
✓ Branch 7 taken 329 times.
30300 if (args[i]->const_for_execution() && !args[i]->has_subquery()) {
4603
4/6
✓ Branch 0 taken 29971 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25824 times.
✓ Branch 3 taken 4142 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
29971 switch (args[i]->result_type()) {
4604 25824 case STRING_RESULT:
4605 case DECIMAL_RESULT: {
4606
1/2
✓ Branch 0 taken 25824 times.
✗ Branch 1 not taken.
25824 get_string(i);
4607 25824 break;
4608 }
4609 4142 case INT_RESULT:
4610
1/2
✓ Branch 0 taken 4142 times.
✗ Branch 1 not taken.
4142 *((longlong *)to) = args[i]->val_int();
4611
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4141 times.
4142 if (args[i]->null_value) continue;
4612 4141 f_args.args[i] = to;
4613 4141 to += ALIGN_SIZE(sizeof(longlong));
4614 4141 break;
4615 5 case REAL_RESULT:
4616
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 *((double *)to) = args[i]->val_real();
4617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (args[i]->null_value) continue;
4618 5 f_args.args[i] = to;
4619 5 to += ALIGN_SIZE(sizeof(double));
4620 5 break;
4621 case ROW_RESULT:
4622 default:
4623 // This case should never be chosen
4624 assert(0);
4625 break;
4626 }
4627 }
4628 }
4629 22734 Udf_func_init init = u_d->func_init;
4630
3/4
✓ Branch 0 taken 22732 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1308 times.
✓ Branch 3 taken 21424 times.
22734 if ((error = (uchar)init(&initid, &f_args, init_msg_buff))) {
4631
1/2
✓ Branch 0 taken 1308 times.
✗ Branch 1 not taken.
1308 my_error(ER_CANT_INITIALIZE_UDF, MYF(0), u_d->name.str, init_msg_buff);
4632 1308 return true;
4633 }
4634 21424 m_init_func_called = true;
4635 21424 return false;
4636 }
4637
4638 21958 bool udf_handler::get_arguments() {
4639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21958 times.
21958 if (error) return true; // Got an error earlier
4640 21958 char *to = num_buffer;
4641
2/2
✓ Branch 0 taken 27830 times.
✓ Branch 1 taken 21958 times.
49788 for (uint i = 0; i < f_args.arg_count; i++) {
4642 27830 f_args.args[i] = nullptr;
4643
4/5
✓ Branch 0 taken 24131 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3625 times.
✓ Branch 3 taken 71 times.
✗ Branch 4 not taken.
27830 switch (f_args.arg_type[i]) {
4644 24131 case STRING_RESULT:
4645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24131 times.
24131 if (get_and_convert_string(i)) return true;
4646 24131 break;
4647 3 case DECIMAL_RESULT:
4648 3 get_string(i);
4649 3 break;
4650 3625 case INT_RESULT:
4651 3625 *((longlong *)to) = args[i]->val_int();
4652
2/2
✓ Branch 0 taken 3616 times.
✓ Branch 1 taken 9 times.
3625 if (!args[i]->null_value) {
4653 3616 f_args.args[i] = to;
4654 3616 to += ALIGN_SIZE(sizeof(longlong));
4655 }
4656 3625 break;
4657 71 case REAL_RESULT:
4658 71 *((double *)to) = args[i]->val_real();
4659
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 3 times.
71 if (!args[i]->null_value) {
4660 68 f_args.args[i] = to;
4661 68 to += ALIGN_SIZE(sizeof(double));
4662 }
4663 71 break;
4664 case ROW_RESULT:
4665 default:
4666 // This case should never be chosen
4667 assert(0);
4668 break;
4669 }
4670 }
4671 21958 return false;
4672 }
4673
4674 85 double udf_handler::val_real(bool *null_value) {
4675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 assert(is_initialized());
4676 85 is_null = 0;
4677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (get_arguments()) {
4678 *null_value = true;
4679 return 0.0;
4680 }
4681 85 Udf_func_double func = (Udf_func_double)u_d->func;
4682 85 double tmp = func(&initid, &f_args, &is_null, &error);
4683
4/4
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 76 times.
85 if (is_null || error) {
4684 9 *null_value = true;
4685 9 return 0.0;
4686 }
4687 76 *null_value = false;
4688 76 return tmp;
4689 }
4690
4691 4733 longlong udf_handler::val_int(bool *null_value) {
4692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4733 times.
4733 assert(is_initialized());
4693 4733 is_null = 0;
4694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4733 times.
4733 if (get_arguments()) {
4695 *null_value = true;
4696 return 0LL;
4697 }
4698
1/2
✓ Branch 0 taken 4733 times.
✗ Branch 1 not taken.
4733 DEBUG_SYNC(current_thd, "execute_uninstall_component");
4699 4733 Udf_func_longlong func = (Udf_func_longlong)u_d->func;
4700 4733 longlong tmp = func(&initid, &f_args, &is_null, &error);
4701
4/4
✓ Branch 0 taken 4689 times.
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 362 times.
✓ Branch 3 taken 4327 times.
4733 if (is_null || error) {
4702 406 *null_value = true;
4703 406 return 0LL;
4704 }
4705 4327 *null_value = false;
4706 4327 return tmp;
4707 }
4708
4709 /**
4710 @return
4711 (String*)NULL in case of NULL values
4712 */
4713 17065 String *udf_handler::val_str(String *str, String *save_str) {
4714 17065 uchar is_null_tmp = 0;
4715 ulong res_length;
4716
1/2
✓ Branch 0 taken 17068 times.
✗ Branch 1 not taken.
17065 DBUG_TRACE;
4717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17068 times.
17068 assert(is_initialized());
4718
4719
2/4
✓ Branch 0 taken 17067 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17067 times.
17068 if (get_arguments()) return nullptr;
4720
4721
3/6
✓ Branch 0 taken 17066 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17066 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17066 times.
✗ Branch 5 not taken.
17067 DEBUG_SYNC(current_thd, "before_string_udf_execution");
4722 17066 Udf_func_string func = reinterpret_cast<Udf_func_string>(u_d->func);
4723
4724
2/2
✓ Branch 0 taken 6736 times.
✓ Branch 1 taken 10332 times.
17066 if ((res_length = str->alloced_length()) <
4725 MAX_FIELD_WIDTH) { // This happens VERY seldom
4726
2/4
✓ Branch 0 taken 6736 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6736 times.
6736 if (str->alloc(MAX_FIELD_WIDTH)) {
4727 error = 1;
4728 return nullptr;
4729 }
4730 }
4731 char *res =
4732
1/2
✓ Branch 0 taken 17068 times.
✗ Branch 1 not taken.
17068 func(&initid, &f_args, str->ptr(), &res_length, &is_null_tmp, &error);
4733
3/8
✓ Branch 0 taken 17068 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17068 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17068 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
17068 DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
4734
6/6
✓ Branch 0 taken 16859 times.
✓ Branch 1 taken 209 times.
✓ Branch 2 taken 16644 times.
✓ Branch 3 taken 215 times.
✓ Branch 4 taken 323 times.
✓ Branch 5 taken 16321 times.
17068 if (is_null_tmp || !res || error) // The !res is for safety
4735 {
4736
3/8
✓ Branch 0 taken 747 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 747 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 747 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
747 DBUG_PRINT("info", ("Null or error"));
4737 747 return nullptr;
4738 }
4739
4740
1/2
✓ Branch 0 taken 16321 times.
✗ Branch 1 not taken.
16321 String *res_str = result_string(res, res_length, str, save_str);
4741
3/8
✓ Branch 0 taken 16321 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16321 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 16321 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
16321 DBUG_PRINT("exit", ("res_str: %s", res_str->ptr()));
4742 16321 return res_str;
4743 17068 }
4744
4745 /*
4746 For the moment, UDF functions are returning DECIMAL values as strings
4747 */
4748
4749 my_decimal *udf_handler::val_decimal(bool *null_value, my_decimal *dec_buf) {
4750 char buf[DECIMAL_MAX_STR_LENGTH + 1];
4751 ulong res_length = DECIMAL_MAX_STR_LENGTH;
4752
4753 assert(is_initialized());
4754
4755 if (get_arguments()) {
4756 *null_value = true;
4757 return nullptr;
4758 }
4759 Udf_func_string func = reinterpret_cast<Udf_func_string>(u_d->func);
4760
4761 char *res = func(&initid, &f_args, buf, &res_length, &is_null, &error);
4762 if (is_null || error) {
4763 *null_value = true;
4764 return nullptr;
4765 }
4766 const char *end = res + res_length;
4767 str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
4768 return dec_buf;
4769 }
4770
4771 48 void udf_handler::clear() {
4772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 assert(is_initialized());
4773 48 is_null = 0;
4774 48 Udf_func_clear func = u_d->func_clear;
4775 48 func(&initid, &is_null, &error);
4776 48 }
4777
4778 74 void udf_handler::add(bool *null_value) {
4779
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 assert(is_initialized());
4780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 74 times.
74 if (get_arguments()) {
4781 *null_value = true;
4782 return;
4783 }
4784 74 Udf_func_add func = u_d->func_add;
4785 74 func(&initid, &f_args, &is_null, &error);
4786
2/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 74 times.
74 *null_value = (bool)(is_null || error);
4787 }
4788
4789 /**
4790 Process the result string returned by the udf() method. The charset
4791 info might have changed therefore updates the same String. If user
4792 used the input String as result string then return the same.
4793
4794 @param [in] res the result string returned by the udf() method.
4795 @param [in] res_length length of the string
4796 @param [out] str The input result string passed to the udf() method
4797 @param [out] save_str Keeps copy of the returned String
4798
4799 @returns A pointer to either the str or save_str that points
4800 to final result String
4801 */
4802 16320 String *udf_handler::result_string(const char *res, size_t res_length,
4803 String *str, String *save_str) {
4804 16320 const auto *charset = m_return_value_extension.charset_info;
4805 16320 String *res_str = nullptr;
4806
2/2
✓ Branch 0 taken 9172 times.
✓ Branch 1 taken 7149 times.
16320 if (res == str->ptr()) {
4807 9172 res_str = str;
4808 9172 res_str->length(res_length);
4809 9172 res_str->set_charset(charset);
4810 } else {
4811 7149 res_str = save_str;
4812 7149 res_str->set(res, res_length, charset);
4813 }
4814 16321 return res_str;
4815 }
4816
4817 /**
4818 Get the details of the input String arguments.
4819
4820 @param [in] index of the argument to be looked in the arguments array
4821 */
4822 25827 void udf_handler::get_string(uint index) {
4823 25827 String *res = args[index]->val_str(&buffers[index]);
4824
2/2
✓ Branch 0 taken 25416 times.
✓ Branch 1 taken 411 times.
25827 if (!args[index]->null_value) {
4825 25416 f_args.args[index] = res->ptr();
4826 25416 f_args.lengths[index] = res->length();
4827 } else {
4828 411 f_args.lengths[index] = 0;
4829 }
4830 25827 }
4831
4832 /**
4833 Get the details of the input String argument.
4834 If the charset of the input argument is not same as specified by the
4835 user then convert the String.
4836
4837 @param [in] index of the argument to be looked in the arguments array
4838
4839 @retval false Able to fetch the argument details
4840 @retval true Otherwise
4841 */
4842 24131 bool udf_handler::get_and_convert_string(uint index) {
4843 24131 String *res = args[index]->val_str(&buffers[index]);
4844
4845 /* m_args_extension.charset_info[index] is a legitimate charset */
4846
4/4
✓ Branch 0 taken 23928 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 23927 times.
✓ Branch 3 taken 1 times.
24131 if (res != nullptr && m_args_extension.charset_info[index] != nullptr) {
4847
2/2
✓ Branch 0 taken 1405 times.
✓ Branch 1 taken 22522 times.
23927 if (res->charset() != m_args_extension.charset_info[index]) {
4848 1405 String temp;
4849 uint dummy;
4850
2/4
✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1405 times.
1405 if (temp.copy(res->ptr(), res->length(), res->charset(),
4851 1405 m_args_extension.charset_info[index], &dummy)) {
4852 return true;
4853 }
4854 1405 *res = std::move(temp);
4855
1/2
✓ Branch 0 taken 1405 times.
✗ Branch 1 not taken.
1405 }
4856 }
4857
2/2
✓ Branch 0 taken 23928 times.
✓ Branch 1 taken 203 times.
24131 if (!args[index]->null_value) {
4858 23928 f_args.args[index] = res->c_ptr_safe();
4859 23928 f_args.lengths[index] = res->length();
4860 } else {
4861 203 f_args.lengths[index] = 0;
4862 }
4863 24131 return false;
4864 }
4865
4866 23187 bool Item_udf_func::itemize(Parse_context *pc, Item **res) {
4867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23189 times.
23187 if (skip_itemize(res)) return false;
4868
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23186 times.
23189 if (super::itemize(pc, res)) return true;
4869 23186 pc->thd->lex->set_has_udf();
4870 23186 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UDF);
4871 23187 pc->thd->lex->safe_to_cache_query = false;
4872 23187 return false;
4873 }
4874
4875 23158 void Item_udf_func::cleanup() {
4876 23158 udf.cleanup();
4877 23160 str_value.mem_free();
4878 23160 Item_func::cleanup();
4879 23160 }
4880
4881 14 void Item_udf_func::print(const THD *thd, String *str,
4882 enum_query_type query_type) const {
4883
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 str->append(func_name());
4884 14 str->append('(');
4885
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 for (uint i = 0; i < arg_count; i++) {
4886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (i != 0) str->append(',');
4887 14 args[i]->print_item_w_name(thd, str, query_type);
4888 }
4889 14 str->append(')');
4890 14 }
4891
4892 67 double Item_func_udf_float::val_real() {
4893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 assert(fixed == 1);
4894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 DBUG_PRINT("info", ("result_type: %d arg_count: %d", args[0]->result_type(),
4895 arg_count));
4896 67 return udf.val_real(&null_value);
4897 }
4898
4899 String *Item_func_udf_float::val_str(String *str) {
4900 assert(fixed == 1);
4901 double nr = val_real();
4902 if (null_value) return nullptr; /* purecov: inspected */
4903 str->set_real(nr, decimals, &my_charset_bin);
4904 return str;
4905 }
4906
4907 4707 longlong Item_func_udf_int::val_int() {
4908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4707 times.
4707 assert(fixed == 1);
4909 4707 return udf.val_int(&null_value);
4910 }
4911
4912 42 String *Item_func_udf_int::val_str(String *str) {
4913
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 assert(fixed == 1);
4914 42 longlong nr = val_int();
4915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (null_value) return nullptr;
4916 42 str->set_int(nr, unsigned_flag, &my_charset_bin);
4917 42 return str;
4918 }
4919
4920 longlong Item_func_udf_decimal::val_int() {
4921 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4922 longlong result;
4923 if (null_value) return 0;
4924 my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
4925 return result;
4926 }
4927
4928 double Item_func_udf_decimal::val_real() {
4929 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4930 double result;
4931 if (null_value) return 0.0;
4932 my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
4933 return result;
4934 }
4935
4936 my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf) {
4937 return udf.val_decimal(&null_value, dec_buf);
4938 }
4939
4940 String *Item_func_udf_decimal::val_str(String *str) {
4941 my_decimal dec_buf, *dec = udf.val_decimal(&null_value, &dec_buf);
4942 if (null_value) return nullptr;
4943 if (str->length() < DECIMAL_MAX_STR_LENGTH)
4944 str->length(DECIMAL_MAX_STR_LENGTH);
4945 my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, false, &dec_buf);
4946 my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, str);
4947 return str;
4948 }
4949
4950 bool Item_func_udf_decimal::resolve_type(THD *) {
4951 set_data_type(MYSQL_TYPE_NEWDECIMAL);
4952 fix_num_length_and_dec();
4953 return false;
4954 }
4955
4956 /* Default max_length is max argument length */
4957
4958 17557 bool Item_func_udf_str::resolve_type(THD *) {
4959 17557 uint result_length = 0;
4960
2/2
✓ Branch 0 taken 17737 times.
✓ Branch 1 taken 17557 times.
35294 for (uint i = 0; i < arg_count; i++)
4961 17737 result_length = max(result_length, args[i]->max_length);
4962 // If the UDF has an init function, this may be overridden later.
4963 17557 set_data_type_string(result_length, &my_charset_bin);
4964 17557 return false;
4965 }
4966
4967 17065 String *Item_func_udf_str::val_str(String *str) {
4968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17065 times.
17065 assert(fixed == 1);
4969 17065 String *res = udf.val_str(str, &str_value);
4970 17068 null_value = !res;
4971 17068 return res;
4972 }
4973
4974 33844 bool Item_source_pos_wait::itemize(Parse_context *pc, Item **res) {
4975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33844 times.
33844 if (skip_itemize(res)) return false;
4976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33844 times.
33844 if (super::itemize(pc, res)) return true;
4977 33844 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
4978 33844 pc->thd->lex->safe_to_cache_query = false;
4979 33844 return false;
4980 }
4981
4982 /**
4983 Wait until we are at or past the given position in the master binlog
4984 on the slave.
4985 */
4986
4987 33839 longlong Item_source_pos_wait::val_int() {
4988
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33839 times.
33839 assert(fixed == 1);
4989 33839 THD *thd = current_thd;
4990 33839 String *log_name = args[0]->val_str(&value);
4991 33839 int event_count = 0;
4992
4993 33839 null_value = false;
4994
4/8
✓ Branch 0 taken 33839 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33839 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 33839 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 33839 times.
33839 if (thd->slave_thread || !log_name || !log_name->length()) {
4995 null_value = true;
4996 return 0;
4997 }
4998 Master_info *mi;
4999 33839 longlong pos = (ulong)args[1]->val_int();
5000
2/2
✓ Branch 0 taken 33830 times.
✓ Branch 1 taken 9 times.
33839 double timeout = (arg_count >= 3) ? args[2]->val_real() : 0;
5001
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 33834 times.
33839 if (timeout < 0) {
5002
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (thd->is_strict_mode()) {
5003 3 my_error(ER_WRONG_ARGUMENTS, MYF(0), "SOURCE_POS_WAIT.");
5004 } else {
5005 2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5006 ER_THD(thd, ER_WRONG_ARGUMENTS), "SOURCE_POS_WAIT.");
5007 2 null_value = true;
5008 }
5009 5 return 0;
5010 }
5011
5012 33834 channel_map.rdlock();
5013
5014
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 33618 times.
33834 if (arg_count == 4) {
5015 String *channel_str;
5016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216 times.
216 if (!(channel_str = args[3]->val_str(&value))) {
5017 null_value = true;
5018 return 0;
5019 }
5020
5021 216 mi = channel_map.get_mi(channel_str->ptr());
5022
5023 } else {
5024
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 33614 times.
33618 if (channel_map.get_num_instances() > 1) {
5025 4 mi = nullptr;
5026 4 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
5027 } else
5028 33614 mi = channel_map.get_default_channel_mi();
5029 }
5030
5031
2/2
✓ Branch 0 taken 33826 times.
✓ Branch 1 taken 8 times.
33834 if (mi != nullptr) mi->inc_reference();
5032
5033 33834 channel_map.unlock();
5034
5035
6/6
✓ Branch 0 taken 33826 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 33804 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 33804 times.
33834 if (mi == nullptr || (event_count = mi->rli->wait_for_pos(thd, log_name, pos,
5036 timeout)) == -2) {
5037 30 null_value = true;
5038 30 event_count = 0;
5039 }
5040
5041
2/2
✓ Branch 0 taken 33826 times.
✓ Branch 1 taken 8 times.
33834 if (mi != nullptr) mi->dec_reference();
5042 33834 return event_count;
5043 }
5044
5045 7 longlong Item_master_pos_wait::val_int() {
5046 7 push_deprecated_warn(current_thd, "MASTER_POS_WAIT", "SOURCE_POS_WAIT");
5047 7 return Item_source_pos_wait::val_int();
5048 }
5049
5050 2277 bool Item_wait_for_executed_gtid_set::itemize(Parse_context *pc, Item **res) {
5051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2277 times.
2277 if (skip_itemize(res)) return false;
5052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2277 times.
2277 if (super::itemize(pc, res)) return true;
5053 /*
5054 It is unsafe because the return value depends on timing. If the timeout
5055 happens, the return value is different from the one in which the function
5056 returns with success.
5057 */
5058 2277 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5059 2277 pc->thd->lex->safe_to_cache_query = false;
5060 2277 return false;
5061 }
5062
5063 /**
5064 Wait until the given gtid_set is found in the executed gtid_set independent
5065 of the slave threads.
5066 */
5067 4050 longlong Item_wait_for_executed_gtid_set::val_int() {
5068
1/2
✓ Branch 0 taken 4050 times.
✗ Branch 1 not taken.
4050 DBUG_TRACE;
5069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4050 times.
4050 assert(fixed);
5070
1/2
✓ Branch 0 taken 4050 times.
✗ Branch 1 not taken.
4050 THD *thd = current_thd;
5071
5072 4050 null_value = false;
5073
5074
1/2
✓ Branch 0 taken 4050 times.
✗ Branch 1 not taken.
4050 String *gtid_text = args[0]->val_str(&value);
5075
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4046 times.
4050 if (gtid_text == nullptr) {
5076 /*
5077 Usually, an argument that is NULL causes an SQL function to return NULL,
5078 however since this is a function with side-effects, a NULL value is
5079 treated as an error.
5080 */
5081
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if (!thd->is_error()) {
5082
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_MALFORMED_GTID_SET_SPECIFICATION, MYF(0), "NULL");
5083 }
5084 4 return error_int();
5085 }
5086
5087 // Waiting for a GTID in a slave thread could cause the slave to
5088 // hang/deadlock.
5089 // @todo: Return error instead of NULL
5090
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4044 times.
4046 if (thd->slave_thread) {
5091 2 return error_int();
5092 }
5093
5094
1/2
✓ Branch 0 taken 4044 times.
✗ Branch 1 not taken.
4044 Gtid_set wait_for_gtid_set(global_sid_map, nullptr);
5095
5096
1/2
✓ Branch 0 taken 4044 times.
✗ Branch 1 not taken.
4044 global_sid_lock->rdlock();
5097
3/4
✓ Branch 0 taken 4044 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4040 times.
4044 if (global_gtid_mode.get() == Gtid_mode::OFF) {
5098
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 global_sid_lock->unlock();
5099
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 my_error(ER_GTID_MODE_OFF, MYF(0), "use WAIT_FOR_EXECUTED_GTID_SET");
5100 4 return error_int();
5101 }
5102
5103
4/6
✓ Branch 0 taken 4040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4040 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4037 times.
4040 if (wait_for_gtid_set.add_gtid_text(gtid_text->c_ptr_safe()) !=
5104 RETURN_STATUS_OK) {
5105
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 global_sid_lock->unlock();
5106 // Error has already been generated.
5107 3 return error_int();
5108 }
5109
5110 // Cannot wait for a GTID that the thread owns since that would
5111 // immediately deadlock.
5112
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4035 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 4036 times.
4039 if (thd->owned_gtid.sidno > 0 &&
5113
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 wait_for_gtid_set.contains_gtid(thd->owned_gtid)) {
5114 char buf[Gtid::MAX_TEXT_LENGTH + 1];
5115
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->owned_gtid.to_string(global_sid_map, buf);
5116
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 global_sid_lock->unlock();
5117
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_WAIT_FOR_EXECUTED_GTID_SET_WHILE_OWNING_A_GTID, MYF(0),
5118 buf);
5119 1 return error_int();
5120 }
5121
5122
1/2
✓ Branch 0 taken 4036 times.
✗ Branch 1 not taken.
4036 gtid_state->begin_gtid_wait();
5123
5124
3/4
✓ Branch 0 taken 3965 times.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 3965 times.
✗ Branch 3 not taken.
4036 double timeout = (arg_count == 2) ? args[1]->val_real() : 0;
5125
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4030 times.
4036 if (timeout < 0) {
5126
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (thd->is_strict_mode()) {
5127
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_WRONG_ARGUMENTS, MYF(0), "WAIT_FOR_EXECUTED_GTID_SET.");
5128 } else {
5129
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5130 ER_THD(thd, ER_WRONG_ARGUMENTS),
5131 "WAIT_FOR_EXECUTED_GTID_SET.");
5132 }
5133
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 gtid_state->end_gtid_wait();
5134
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 global_sid_lock->unlock();
5135 6 return error_int();
5136 }
5137
5138
1/2
✓ Branch 0 taken 4030 times.
✗ Branch 1 not taken.
4030 bool result = gtid_state->wait_for_gtid_set(thd, &wait_for_gtid_set, timeout);
5139
1/2
✓ Branch 0 taken 4030 times.
✗ Branch 1 not taken.
4030 global_sid_lock->unlock();
5140
1/2
✓ Branch 0 taken 4030 times.
✗ Branch 1 not taken.
4030 gtid_state->end_gtid_wait();
5141
5142 4030 return result;
5143 4050 }
5144
5145 19 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a)
5146 19 : Item_int_func(pos, a) {
5147
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5148 "WAIT_FOR_EXECUTED_GTID_SET");
5149 19 }
5150
5151 1917 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a,
5152 1917 Item *b)
5153 1917 : Item_int_func(pos, a, b) {
5154
2/4
✓ Branch 0 taken 1917 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1917 times.
✗ Branch 3 not taken.
1917 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5155 "WAIT_FOR_EXECUTED_GTID_SET");
5156 1917 }
5157
5158 88 Item_master_gtid_set_wait::Item_master_gtid_set_wait(const POS &pos, Item *a,
5159 88 Item *b, Item *c)
5160 88 : Item_int_func(pos, a, b, c) {
5161
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
88 push_deprecated_warn(current_thd, "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS",
5162 "WAIT_FOR_EXECUTED_GTID_SET");
5163 88 }
5164
5165 2024 bool Item_master_gtid_set_wait::itemize(Parse_context *pc, Item **res) {
5166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2024 times.
2024 if (skip_itemize(res)) return false;
5167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2024 times.
2024 if (super::itemize(pc, res)) return true;
5168 2024 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5169 2024 pc->thd->lex->safe_to_cache_query = false;
5170 2024 return false;
5171 }
5172
5173 2021 longlong Item_master_gtid_set_wait::val_int() {
5174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2021 times.
2021 assert(fixed);
5175
1/2
✓ Branch 0 taken 2021 times.
✗ Branch 1 not taken.
2021 DBUG_TRACE;
5176 2021 int event_count = 0;
5177
5178 2021 null_value = false;
5179
5180
1/2
✓ Branch 0 taken 2021 times.
✗ Branch 1 not taken.
2021 String *gtid = args[0]->val_str(&value);
5181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2021 times.
2021 if (gtid == nullptr) {
5182 return error_int();
5183 }
5184
5185
1/2
✓ Branch 0 taken 2021 times.
✗ Branch 1 not taken.
2021 THD *thd = current_thd;
5186 2021 Master_info *mi = nullptr;
5187
3/4
✓ Branch 0 taken 2003 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 2003 times.
✗ Branch 3 not taken.
2021 double timeout = (arg_count >= 2) ? args[1]->val_real() : 0;
5188
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2017 times.
2021 if (timeout < 0) {
5189
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (thd->is_strict_mode()) {
5190
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 my_error(ER_WRONG_ARGUMENTS, MYF(0),
5191 "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.");
5192 } else {
5193
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5194 ER_THD(thd, ER_WRONG_ARGUMENTS),
5195 "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.");
5196 }
5197 4 return error_int();
5198 }
5199
5200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2017 times.
2017 if (thd->slave_thread) {
5201 return error_int();
5202 }
5203
5204
1/2
✓ Branch 0 taken 2017 times.
✗ Branch 1 not taken.
2017 channel_map.rdlock();
5205
5206 /* If replication channel is mentioned */
5207
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 1930 times.
2017 if (arg_count == 3) {
5208 String *channel_str;
5209
2/4
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 87 times.
87 if (!(channel_str = args[2]->val_str(&value))) {
5210 channel_map.unlock();
5211 return error_int();
5212 }
5213
1/2
✓ Branch 0 taken 87 times.
✗ Branch 1 not taken.
87 mi = channel_map.get_mi(channel_str->ptr());
5214 } else {
5215
3/4
✓ Branch 0 taken 1930 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1927 times.
1930 if (channel_map.get_num_instances() > 1) {
5216
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 channel_map.unlock();
5217 3 mi = nullptr;
5218
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 my_error(ER_SLAVE_MULTIPLE_CHANNELS_CMD, MYF(0));
5219 3 return error_int();
5220 } else
5221
1/2
✓ Branch 0 taken 1927 times.
✗ Branch 1 not taken.
1927 mi = channel_map.get_default_channel_mi();
5222 }
5223
5224
4/4
✓ Branch 0 taken 2013 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2013 times.
4027 if ((mi != nullptr) &&
5225
3/4
✓ Branch 0 taken 2013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2012 times.
2013 mi->rli->m_assign_gtids_to_anonymous_transactions_info.get_type() >
5226 Assign_gtids_to_anonymous_transactions_info::enum_type::AGAT_OFF) {
5227
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_CANT_SET_ANONYMOUS_TO_GTID_AND_WAIT_UNTIL_SQL_THD_AFTER_GTIDS,
5228 MYF(0));
5229
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
5230 1 return error_int();
5231 }
5232
3/4
✓ Branch 0 taken 2013 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2012 times.
2013 if (global_gtid_mode.get() == Gtid_mode::OFF) {
5233
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 channel_map.unlock();
5234 1 return error_int();
5235 }
5236
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 gtid_state->begin_gtid_wait();
5237
5238
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 if (mi != nullptr) mi->inc_reference();
5239
5240
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 channel_map.unlock();
5241
5242 2012 bool null_result = false;
5243
5244
2/4
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2012 times.
✗ Branch 3 not taken.
2012 if (mi != nullptr && mi->rli != nullptr) {
5245
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 event_count = mi->rli->wait_for_gtid_set(thd, gtid, timeout);
5246
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2011 times.
2012 if (event_count == -2) {
5247 1 null_result = true;
5248 }
5249 } else {
5250 /*
5251 Replication has not been set up, we should return NULL;
5252 */
5253 null_result = true;
5254 }
5255
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 if (mi != nullptr) mi->dec_reference();
5256
5257
1/2
✓ Branch 0 taken 2012 times.
✗ Branch 1 not taken.
2012 gtid_state->end_gtid_wait();
5258
5259
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2011 times.
2012 return null_result ? error_int() : event_count;
5260 2021 }
5261
5262 /**
5263 Return 1 if both arguments are Gtid_sets and the first is a subset
5264 of the second. Generate an error if any of the arguments is not a
5265 Gtid_set.
5266 */
5267 5892 longlong Item_func_gtid_subset::val_int() {
5268
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 DBUG_TRACE;
5269
5270
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5892 times.
5892 assert(fixed);
5271
5272 5892 null_value = false;
5273
5274 // Evaluate strings without lock
5275
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 String *string1 = args[0]->val_str(&buf1);
5276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5892 times.
5892 if (string1 == nullptr) {
5277 return error_int();
5278 }
5279
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 String *string2 = args[1]->val_str(&buf2);
5280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5892 times.
5892 if (string2 == nullptr) {
5281 return error_int();
5282 }
5283
5284
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 const char *charp1 = string1->c_ptr_safe();
5285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5892 times.
5892 assert(charp1 != nullptr);
5286
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 const char *charp2 = string2->c_ptr_safe();
5287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5892 times.
5892 assert(charp2 != nullptr);
5288 5892 int ret = 1;
5289 enum_return_status status;
5290
5291
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 Sid_map sid_map(nullptr /*no rwlock*/);
5292 // compute sets while holding locks
5293
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 const Gtid_set sub_set(&sid_map, charp1, &status);
5294
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 if (status == RETURN_STATUS_OK) {
5295
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 const Gtid_set super_set(&sid_map, charp2, &status);
5296
1/2
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
5892 if (status == RETURN_STATUS_OK) {
5297
3/4
✓ Branch 0 taken 5892 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5885 times.
✓ Branch 3 taken 7 times.
5892 ret = sub_set.is_subset(&super_set) ? 1 : 0;
5298 }
5299 5892 }
5300 5892 return ret;
5301 5892 }
5302
5303 /**
5304 Enables a session to wait on a condition until a timeout or a network
5305 disconnect occurs.
5306
5307 @remark The connection is polled every m_interrupt_interval nanoseconds.
5308 */
5309
5310 class Interruptible_wait {
5311 THD *m_thd;
5312 struct timespec m_abs_timeout;
5313 static const ulonglong m_interrupt_interval;
5314
5315 public:
5316 18418 Interruptible_wait(THD *thd) : m_thd(thd) {}
5317
5318 ~Interruptible_wait() = default;
5319
5320 public:
5321 /**
5322 Set the absolute timeout.
5323
5324 @param timeout The amount of time in nanoseconds to wait
5325 */
5326 18404 void set_timeout(ulonglong timeout) {
5327 /*
5328 Calculate the absolute system time at the start so it can
5329 be controlled in slices. It relies on the fact that once
5330 the absolute time passes, the timed wait call will fail
5331 automatically with a timeout error.
5332 */
5333 18404 set_timespec_nsec(&m_abs_timeout, timeout);
5334 18404 }
5335
5336 /** The timed wait. */
5337 int wait(mysql_cond_t *, mysql_mutex_t *);
5338 };
5339
5340 /** Time to wait before polling the connection status. */
5341 const ulonglong Interruptible_wait::m_interrupt_interval = 5 * 1000000000ULL;
5342
5343 /**
5344 Wait for a given condition to be signaled.
5345
5346 @param cond The condition variable to wait on.
5347 @param mutex The associated mutex.
5348
5349 @remark The absolute timeout is preserved across calls.
5350
5351 @retval return value from mysql_cond_timedwait
5352 */
5353
5354 18433 int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex) {
5355 int error;
5356 struct timespec timeout;
5357
5358 while (true) {
5359 /* Wait for a fixed interval. */
5360
1/2
✓ Branch 0 taken 18433 times.
✗ Branch 1 not taken.
18433 set_timespec_nsec(&timeout, m_interrupt_interval);
5361
5362 /* But only if not past the absolute timeout. */
5363
2/2
✓ Branch 0 taken 18375 times.
✓ Branch 1 taken 58 times.
18433 if (cmp_timespec(&timeout, &m_abs_timeout) > 0) timeout = m_abs_timeout;
5364
5365
1/2
✓ Branch 0 taken 18406 times.
✗ Branch 1 not taken.
18433 error = mysql_cond_timedwait(cond, mutex, &timeout);
5366
2/2
✓ Branch 0 taken 18375 times.
✓ Branch 1 taken 31 times.
18406 if (is_timeout(error)) {
5367 /* Return error if timed out or connection is broken. */
5368
7/8
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 18339 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 18345 times.
✓ Branch 7 taken 30 times.
18375 if (!cmp_timespec(&timeout, &m_abs_timeout) || !m_thd->is_connected())
5369 18345 break;
5370 }
5371 /* Otherwise, propagate status to the caller. */
5372 else
5373 31 break;
5374 }
5375
5376 18376 return error;
5377 }
5378
5379 /*
5380 User-level locks implementation.
5381 */
5382
5383 /**
5384 For locks with EXPLICIT duration, MDL returns a new ticket
5385 every time a lock is granted. This allows to implement recursive
5386 locks without extra allocation or additional data structures, such
5387 as below. However, if there are too many tickets in the same
5388 MDL_context, MDL_context::find_ticket() is getting too slow,
5389 since it's using a linear search.
5390 This is why a separate structure is allocated for a user
5391 level lock held by connection, and before requesting a new lock from MDL,
5392 GET_LOCK() checks thd->ull_hash if such lock is already granted,
5393 and if so, simply increments a reference counter.
5394 */
5395
5396 struct User_level_lock {
5397 MDL_ticket *ticket;
5398 uint refs;
5399 };
5400
5401 /**
5402 Release all user level locks for this THD.
5403 */
5404
5405 1325839 void mysql_ull_cleanup(THD *thd) {
5406
1/2
✓ Branch 0 taken 1325993 times.
✗ Branch 1 not taken.
1325839 DBUG_TRACE;
5407
5408
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 1325920 times.
1326055 for (const auto &key_and_value : thd->ull_hash) {
5409 62 User_level_lock *ull = key_and_value.second;
5410
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 thd->mdl_context.release_lock(ull->ticket);
5411
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 my_free(ull);
5412 }
5413
5414 1325920 thd->ull_hash.clear();
5415 1325856 }
5416
5417 /**
5418 Set explicit duration for metadata locks corresponding to
5419 user level locks to protect them from being released at the end
5420 of transaction.
5421 */
5422
5423 1 void mysql_ull_set_explicit_lock_duration(THD *thd) {
5424
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 DBUG_TRACE;
5425
5426
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (const auto &key_and_value : thd->ull_hash) {
5427 1 User_level_lock *ull = key_and_value.second;
5428
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 thd->mdl_context.set_lock_duration(ull->ticket, MDL_EXPLICIT);
5429 }
5430 1 }
5431
5432 /**
5433 When MDL detects a lock wait timeout, it pushes an error into the statement
5434 diagnostics area. For GET_LOCK(), lock wait timeout is not an error, but a
5435 special return value (0). NULL is returned in case of error. Capture and
5436 suppress lock wait timeout.
5437 We also convert ER_LOCK_DEADLOCK error to ER_USER_LOCK_DEADLOCK error.
5438 The former means that implicit rollback of transaction has occurred
5439 which doesn't (and should not) happen when we get deadlock while waiting
5440 for user-level lock.
5441 */
5442
5443 class User_level_lock_wait_error_handler : public Internal_error_handler {
5444 public:
5445 6451 User_level_lock_wait_error_handler() : m_lock_wait_timeout(false) {}
5446
5447 18 bool got_timeout() const { return m_lock_wait_timeout; }
5448
5449 18 bool handle_condition(THD *, uint sql_errno, const char *,
5450 Sql_condition::enum_severity_level *,
5451 const char *) override {
5452
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (sql_errno == ER_LOCK_WAIT_TIMEOUT) {
5453 9 m_lock_wait_timeout = true;
5454 9 return true;
5455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 } else if (sql_errno == ER_LOCK_DEADLOCK) {
5456 my_error(ER_USER_LOCK_DEADLOCK, MYF(0));
5457 return true;
5458 }
5459
5460 9 return false;
5461 }
5462
5463 private:
5464 bool m_lock_wait_timeout;
5465 };
5466
5467 class MDL_lock_get_owner_thread_id_visitor : public MDL_context_visitor {
5468 public:
5469 73 MDL_lock_get_owner_thread_id_visitor() : m_owner_id(0) {}
5470
5471 27 void visit_context(const MDL_context *ctx) override {
5472 27 m_owner_id = ctx->get_owner()->get_thd()->thread_id();
5473 27 }
5474
5475 73 my_thread_id get_owner_id() const { return m_owner_id; }
5476
5477 private:
5478 my_thread_id m_owner_id;
5479 };
5480
5481 /**
5482 Helper function which checks if user-level lock name is acceptable
5483 and converts it to system charset (utf8). Error is emitted if name
5484 is not acceptable. Name is also lowercased to ensure that user-level
5485 lock names are treated in case-insensitive fashion even though MDL
5486 subsystem which used by implementation does binary comparison of keys.
5487
5488 @param buff Buffer for lowercased name in system charset of
5489 NAME_LEN + 1 bytes length.
5490 @param org_name Original string passed as name parameter to
5491 user-level lock function.
5492
5493 @return True in case of error, false on success.
5494 */
5495
5496 12924 static bool check_and_convert_ull_name(char *buff, const String *org_name) {
5497
3/6
✓ Branch 0 taken 12924 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12924 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12924 times.
12924 if (!org_name || !org_name->length()) {
5498 my_error(ER_USER_LOCK_WRONG_NAME, MYF(0), (org_name ? "" : "NULL"));
5499 return true;
5500 }
5501
5502 const char *well_formed_error_pos;
5503 const char *cannot_convert_error_pos;
5504 const char *from_end_pos;
5505 size_t bytes_copied;
5506
5507
1/2
✓ Branch 0 taken 12924 times.
✗ Branch 1 not taken.
12924 bytes_copied = well_formed_copy_nchars(
5508 system_charset_info, buff, NAME_LEN, org_name->charset(), org_name->ptr(),
5509 org_name->length(), NAME_CHAR_LEN, &well_formed_error_pos,
5510 &cannot_convert_error_pos, &from_end_pos);
5511
5512
3/6
✓ Branch 0 taken 12924 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12924 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12924 times.
25848 if (well_formed_error_pos || cannot_convert_error_pos ||
5513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12924 times.
12924 from_end_pos < org_name->ptr() + org_name->length()) {
5514 ErrConvString err(org_name);
5515 my_error(ER_USER_LOCK_WRONG_NAME, MYF(0), err.ptr());
5516 return true;
5517 }
5518
5519 12924 buff[bytes_copied] = '\0';
5520
5521
1/2
✓ Branch 0 taken 12924 times.
✗ Branch 1 not taken.
12924 my_casedn_str(system_charset_info, buff);
5522
5523 12924 return false;
5524 }
5525
5526 7106 bool Item_func_get_lock::itemize(Parse_context *pc, Item **res) {
5527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7106 times.
7106 if (skip_itemize(res)) return false;
5528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7106 times.
7106 if (super::itemize(pc, res)) return true;
5529 7106 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5530 7106 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5531 7106 return false;
5532 }
5533
5534 /**
5535 Get a user level lock.
5536
5537 @note Sets null_value to true on error.
5538
5539 @note This means that SQL-function GET_LOCK() returns:
5540 1 - if lock was acquired.
5541 0 - if lock was not acquired due to timeout.
5542 NULL - in case of error such as bad lock name, deadlock,
5543 thread being killed (also error is emitted).
5544
5545 @retval
5546 1 : Got lock
5547 @retval
5548 0 : Timeout, error.
5549 */
5550
5551 6486 longlong Item_func_get_lock::val_int() {
5552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6486 times.
6486 assert(fixed == 1);
5553
1/2
✓ Branch 0 taken 6486 times.
✗ Branch 1 not taken.
6486 String *res = args[0]->val_str(&value);
5554
1/2
✓ Branch 0 taken 6486 times.
✗ Branch 1 not taken.
6486 ulonglong timeout = args[1]->val_int();
5555 char name[NAME_LEN + 1];
5556
1/2
✓ Branch 0 taken 6486 times.
✗ Branch 1 not taken.
6486 THD *thd = current_thd;
5557
1/2
✓ Branch 0 taken 6486 times.
✗ Branch 1 not taken.
6486 DBUG_TRACE;
5558
5559 6486 null_value = true;
5560 /*
5561 In slave thread no need to get locks, everything is serialized. Anyway
5562 there is no way to make GET_LOCK() work on slave like it did on master
5563 (i.e. make it return exactly the same value) because we don't have the
5564 same other concurrent threads environment. No matter what we return here,
5565 it's not guaranteed to be same as on master. So we always return 1.
5566 */
5567
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6473 times.
6486 if (thd->slave_thread) {
5568 13 null_value = false;
5569 13 return 1;
5570 }
5571
5572
2/4
✓ Branch 0 taken 6473 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6473 times.
6473 if (check_and_convert_ull_name(name, res)) return 0;
5573
5574
3/8
✓ Branch 0 taken 6473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6473 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6473 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6473 DBUG_PRINT("info", ("lock %s, thd=%lu", name, (ulong)thd->real_id));
5575
5576 /*
5577 Convert too big and negative timeout values to INT_MAX32.
5578 This gives robust, "infinite" wait on all platforms.
5579 */
5580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6473 times.
6473 if (timeout > INT_MAX32) timeout = INT_MAX32;
5581
5582 6473 MDL_request ull_request;
5583
1/2
✓ Branch 0 taken 6473 times.
✗ Branch 1 not taken.
6473 MDL_REQUEST_INIT(&ull_request, MDL_key::USER_LEVEL_LOCK, "", name,
5584 MDL_EXCLUSIVE, MDL_EXPLICIT);
5585 12946 std::string ull_key(pointer_cast<const char *>(ull_request.key.ptr()),
5586
2/4
✓ Branch 0 taken 6473 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6473 times.
✗ Branch 3 not taken.
6473 ull_request.key.length());
5587
5588
1/2
✓ Branch 0 taken 6473 times.
✗ Branch 1 not taken.
6473 const auto it = thd->ull_hash.find(ull_key);
5589
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6451 times.
6473 if (it != thd->ull_hash.end()) {
5590 /* Recursive lock. */
5591 22 it->second->refs++;
5592 22 null_value = false;
5593 22 return 1;
5594 }
5595
5596 6451 User_level_lock_wait_error_handler error_handler;
5597
5598
1/2
✓ Branch 0 taken 6451 times.
✗ Branch 1 not taken.
6451 thd->push_internal_handler(&error_handler);
5599 bool error =
5600
1/2
✓ Branch 0 taken 6451 times.
✗ Branch 1 not taken.
6451 thd->mdl_context.acquire_lock(&ull_request, static_cast<ulong>(timeout));
5601
1/2
✓ Branch 0 taken 6451 times.
✗ Branch 1 not taken.
6451 (void)thd->pop_internal_handler();
5602
5603
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6433 times.
6451 if (error) {
5604 /*
5605 Return 0 in case of timeout and NULL in case of deadlock/other
5606 errors. In the latter case error (e.g. ER_USER_LOCK_DEADLOCK)
5607 will be reported as well.
5608 */
5609
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (error_handler.got_timeout()) null_value = false;
5610 18 return 0;
5611 }
5612
5613 6433 User_level_lock *ull = nullptr;
5614 6433 ull = reinterpret_cast<User_level_lock *>(
5615
1/2
✓ Branch 0 taken 6433 times.
✗ Branch 1 not taken.
6433 my_malloc(key_memory_User_level_lock, sizeof(User_level_lock), MYF(0)));
5616
5617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6433 times.
6433 if (ull == nullptr) {
5618 thd->mdl_context.release_lock(ull_request.ticket);
5619 return 0;
5620 }
5621
5622 6433 ull->ticket = ull_request.ticket;
5623 6433 ull->refs = 1;
5624
5625
1/2
✓ Branch 0 taken 6433 times.
✗ Branch 1 not taken.
6433 thd->ull_hash.emplace(ull_key, ull);
5626 6433 null_value = false;
5627
5628 6433 return 1;
5629 6486 }
5630
5631 6980 bool Item_func_release_lock::itemize(Parse_context *pc, Item **res) {
5632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6980 times.
6980 if (skip_itemize(res)) return false;
5633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6980 times.
6980 if (super::itemize(pc, res)) return true;
5634 6980 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5635 6980 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5636 6980 return false;
5637 }
5638
5639 /**
5640 Release a user level lock.
5641
5642 @note Sets null_value to true on error/if no connection holds such lock.
5643
5644 @note This means that SQL-function RELEASE_LOCK() returns:
5645 1 - if lock was held by this connection and was released.
5646 0 - if lock was held by some other connection (and was not released).
5647 NULL - if name of lock is bad or if it was not held by any connection
5648 (in the former case also error will be emitted),
5649
5650 @return
5651 - 1 if lock released
5652 - 0 if lock wasn't held/error.
5653 */
5654
5655 6384 longlong Item_func_release_lock::val_int() {
5656
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
6384 assert(fixed == 1);
5657
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 String *res = args[0]->val_str(&value);
5658 char name[NAME_LEN + 1];
5659
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 THD *thd = current_thd;
5660
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 DBUG_TRACE;
5661
5662 6384 null_value = true;
5663
5664
2/4
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6384 times.
6384 if (check_and_convert_ull_name(name, res)) return 0;
5665
5666
3/8
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6384 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 6384 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6384 DBUG_PRINT("info", ("lock %s", name));
5667
5668 6384 MDL_key ull_key;
5669
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5670
5671
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 const auto it = thd->ull_hash.find(
5672
2/4
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6384 times.
✗ Branch 3 not taken.
12768 std::string(pointer_cast<const char *>(ull_key.ptr()), ull_key.length()));
5673
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6378 times.
6384 if (it == thd->ull_hash.end()) {
5674 /*
5675 When RELEASE_LOCK() is called for lock which is not owned by the
5676 connection it should return 0 or NULL depending on whether lock
5677 is owned by any other connection or not.
5678 */
5679 6 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5680
5681
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor))
5682 return 0;
5683
5684 6 null_value = get_owner_visitor.get_owner_id() == 0;
5685
5686 6 return 0;
5687 6 }
5688 6378 User_level_lock *ull = it->second;
5689
5690 6378 null_value = false;
5691
2/2
✓ Branch 0 taken 6371 times.
✓ Branch 1 taken 7 times.
6378 if (--ull->refs == 0) {
5692
1/2
✓ Branch 0 taken 6371 times.
✗ Branch 1 not taken.
6371 thd->ull_hash.erase(it);
5693
1/2
✓ Branch 0 taken 6371 times.
✗ Branch 1 not taken.
6371 thd->mdl_context.release_lock(ull->ticket);
5694
1/2
✓ Branch 0 taken 6371 times.
✗ Branch 1 not taken.
6371 my_free(ull);
5695 }
5696 6378 return 1;
5697 6384 }
5698
5699 9 bool Item_func_release_all_locks::itemize(Parse_context *pc, Item **res) {
5700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (skip_itemize(res)) return false;
5701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (super::itemize(pc, res)) return true;
5702 9 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5703 9 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5704 9 return false;
5705 }
5706
5707 /**
5708 Release all user level lock held by connection.
5709
5710 @return Number of locks released including recursive lock count.
5711 */
5712
5713 5 longlong Item_func_release_all_locks::val_int() {
5714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(fixed == 1);
5715
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 THD *thd = current_thd;
5716 5 uint result = 0;
5717
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 DBUG_TRACE;
5718
5719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 for (const auto &key_and_value : thd->ull_hash) {
5720 User_level_lock *ull = key_and_value.second;
5721 thd->mdl_context.release_lock(ull->ticket);
5722 result += ull->refs;
5723 my_free(ull);
5724 }
5725 5 thd->ull_hash.clear();
5726
5727 5 return result;
5728 5 }
5729
5730 48 bool Item_func_is_free_lock::itemize(Parse_context *pc, Item **res) {
5731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (skip_itemize(res)) return false;
5732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (super::itemize(pc, res)) return true;
5733 48 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5734 48 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5735 48 return false;
5736 }
5737
5738 /**
5739 Check if user level lock is free.
5740
5741 @note Sets null_value=true on error.
5742
5743 @note As result SQL-function IS_FREE_LOCK() returns:
5744 1 - if lock is free,
5745 0 - if lock is in use
5746 NULL - if lock name is bad or OOM (also error is emitted).
5747
5748 @retval
5749 1 Available
5750 @retval
5751 0 Already taken, or error
5752 */
5753
5754 39 longlong Item_func_is_free_lock::val_int() {
5755
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 assert(fixed == 1);
5756 39 value.length(0);
5757
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 String *res = args[0]->val_str(&value);
5758 char name[NAME_LEN + 1];
5759
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 THD *thd = current_thd;
5760
5761 39 null_value = true;
5762
5763
2/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
39 if (check_and_convert_ull_name(name, res)) return 0;
5764
5765 39 MDL_key ull_key;
5766
1/2
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
39 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5767
5768 39 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5769
5770
2/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
39 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor)) return 0;
5771
5772 39 null_value = false;
5773 39 return (get_owner_visitor.get_owner_id() == 0);
5774 39 }
5775
5776 620 bool Item_func_is_used_lock::itemize(Parse_context *pc, Item **res) {
5777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
620 if (skip_itemize(res)) return false;
5778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 620 times.
620 if (super::itemize(pc, res)) return true;
5779 620 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5780 620 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5781 620 return false;
5782 }
5783
5784 /**
5785 Check if user level lock is used and return connection id of owner.
5786
5787 @note Sets null_value=true if lock is free/on error.
5788
5789 @note SQL-function IS_USED_LOCK() returns:
5790 # - connection id of lock owner if lock is acquired.
5791 NULL - if lock is free or on error (in the latter case
5792 also error is emitted).
5793
5794 @return Connection id of lock owner, 0 if lock is free/on error.
5795 */
5796
5797 28 longlong Item_func_is_used_lock::val_int() {
5798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 assert(fixed == 1);
5799
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 String *res = args[0]->val_str(&value);
5800 char name[NAME_LEN + 1];
5801
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 THD *thd = current_thd;
5802
5803 28 null_value = true;
5804
5805
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
28 if (check_and_convert_ull_name(name, res)) return 0;
5806
5807 28 MDL_key ull_key;
5808
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 ull_key.mdl_key_init(MDL_key::USER_LEVEL_LOCK, "", name);
5809
5810 28 MDL_lock_get_owner_thread_id_visitor get_owner_visitor;
5811
5812
2/4
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
28 if (thd->mdl_context.find_lock_owner(&ull_key, &get_owner_visitor)) return 0;
5813
5814 28 my_thread_id thread_id = get_owner_visitor.get_owner_id();
5815
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 13 times.
28 if (thread_id == 0) return 0;
5816
5817 13 null_value = false;
5818 13 return thread_id;
5819 28 }
5820
5821 1374 bool Item_func_last_insert_id::itemize(Parse_context *pc, Item **res) {
5822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1374 times.
1374 if (skip_itemize(res)) return false;
5823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1374 times.
1374 if (super::itemize(pc, res)) return true;
5824 1374 pc->thd->lex->safe_to_cache_query = false;
5825 1374 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5826 1374 return false;
5827 }
5828
5829 1855 longlong Item_func_last_insert_id::val_int() {
5830 1855 THD *thd = current_thd;
5831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1855 times.
1855 assert(fixed == 1);
5832
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1837 times.
1855 if (arg_count) {
5833 18 longlong value = args[0]->val_int();
5834 18 null_value = args[0]->null_value;
5835 /*
5836 LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
5837 documented in the manual. We don't want to touch
5838 first_successful_insert_id_in_cur_stmt because it would make
5839 LAST_INSERT_ID(X) take precedence over an generated auto_increment
5840 value for this row.
5841 */
5842 18 thd->arg_of_last_insert_id_function = true;
5843 18 thd->first_successful_insert_id_in_prev_stmt = value;
5844 18 return value;
5845 }
5846 return static_cast<longlong>(
5847 1837 thd->read_first_successful_insert_id_in_prev_stmt());
5848 }
5849
5850 34 bool Item_func_benchmark::itemize(Parse_context *pc, Item **res) {
5851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (skip_itemize(res)) return false;
5852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 if (super::itemize(pc, res)) return true;
5853 34 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5854 34 return false;
5855 }
5856
5857 /* This function is just used to test speed of different functions */
5858
5859 32 longlong Item_func_benchmark::val_int() {
5860
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 assert(fixed == 1);
5861 char buff[MAX_FIELD_WIDTH];
5862 32 String tmp(buff, sizeof(buff), &my_charset_bin);
5863 32 my_decimal tmp_decimal;
5864
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 THD *thd = current_thd;
5865 ulonglong loop_count;
5866
5867
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 loop_count = (ulonglong)args[0]->val_int();
5868
5869
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 2 times.
32 if (args[0]->null_value ||
5870
3/4
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 29 times.
30 (!args[0]->unsigned_flag && (((longlong)loop_count) < 0))) {
5871
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!args[0]->null_value) {
5872 char errbuff[22];
5873
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 llstr(((longlong)loop_count), errbuff);
5874
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(current_thd, Sql_condition::SL_WARNING,
5875 ER_WRONG_VALUE_FOR_TYPE,
5876
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_WRONG_VALUE_FOR_TYPE), "count",
5877 errbuff, "benchmark");
5878 }
5879
5880 3 null_value = true;
5881 3 return 0;
5882 }
5883
5884 29 null_value = false;
5885
5/6
✓ Branch 0 taken 1440 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 1440 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1440 times.
✓ Branch 5 taken 29 times.
1469 for (ulonglong loop = 0; loop < loop_count && !thd->killed; loop++) {
5886
5/7
✓ Branch 0 taken 1440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 1000 times.
✓ Branch 4 taken 100 times.
✓ Branch 5 taken 300 times.
✗ Branch 6 not taken.
1440 switch (args[1]->result_type()) {
5887 40 case REAL_RESULT:
5888
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 (void)args[1]->val_real();
5889 40 break;
5890 1000 case INT_RESULT:
5891
1/2
✓ Branch 0 taken 1000 times.
✗ Branch 1 not taken.
1000 (void)args[1]->val_int();
5892 1000 break;
5893 100 case STRING_RESULT:
5894
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 (void)args[1]->val_str(&tmp);
5895 100 break;
5896 300 case DECIMAL_RESULT:
5897
1/2
✓ Branch 0 taken 300 times.
✗ Branch 1 not taken.
300 (void)args[1]->val_decimal(&tmp_decimal);
5898 300 break;
5899 case ROW_RESULT:
5900 default:
5901 // This case should never be chosen
5902 assert(0);
5903 return 0;
5904 }
5905 }
5906 29 return 0;
5907 32 }
5908
5909 1 void Item_func_benchmark::print(const THD *thd, String *str,
5910 enum_query_type query_type) const {
5911 1 str->append(STRING_WITH_LEN("benchmark("));
5912 1 args[0]->print(thd, str, query_type);
5913 1 str->append(',');
5914 1 args[1]->print(thd, str, query_type);
5915 1 str->append(')');
5916 1 }
5917
5918 /**
5919 Lock which is used to implement interruptible wait for SLEEP() function.
5920 */
5921
5922 mysql_mutex_t LOCK_item_func_sleep;
5923
5924 #ifdef HAVE_PSI_INTERFACE
5925 static PSI_mutex_key key_LOCK_item_func_sleep;
5926
5927 static PSI_mutex_info item_func_sleep_mutexes[] = {
5928 {&key_LOCK_item_func_sleep, "LOCK_item_func_sleep", PSI_FLAG_SINGLETON, 0,
5929 PSI_DOCUMENT_ME}};
5930
5931 12108 static void init_item_func_sleep_psi_keys() {
5932 int count;
5933
5934 12108 count = static_cast<int>(array_elements(item_func_sleep_mutexes));
5935 12108 mysql_mutex_register("sql", item_func_sleep_mutexes, count);
5936 12108 }
5937 #endif
5938
5939 static bool item_func_sleep_inited = false;
5940
5941 12108 void item_func_sleep_init() {
5942 #ifdef HAVE_PSI_INTERFACE
5943 12108 init_item_func_sleep_psi_keys();
5944 #endif
5945
5946 12108 mysql_mutex_init(key_LOCK_item_func_sleep, &LOCK_item_func_sleep,
5947 MY_MUTEX_INIT_SLOW);
5948 12108 item_func_sleep_inited = true;
5949 12108 }
5950
5951 10524 void item_func_sleep_free() {
5952
2/2
✓ Branch 0 taken 10490 times.
✓ Branch 1 taken 34 times.
10524 if (item_func_sleep_inited) {
5953 10490 item_func_sleep_inited = false;
5954 10490 mysql_mutex_destroy(&LOCK_item_func_sleep);
5955 }
5956 10524 }
5957
5958 16072 bool Item_func_sleep::itemize(Parse_context *pc, Item **res) {
5959
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16073 times.
16072 if (skip_itemize(res)) return false;
5960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16072 times.
16073 if (super::itemize(pc, res)) return true;
5961 16072 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
5962 16073 pc->thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
5963 16073 return false;
5964 }
5965
5966 /** This function is just used to create tests with time gaps. */
5967
5968 18418 longlong Item_func_sleep::val_int() {
5969
1/2
✓ Branch 0 taken 18418 times.
✗ Branch 1 not taken.
18418 THD *thd = current_thd;
5970 18418 Interruptible_wait timed_cond(thd);
5971 mysql_cond_t cond;
5972 double timeout;
5973 int error;
5974
5975
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18418 times.
18418 assert(fixed == 1);
5976
5977
1/2
✓ Branch 0 taken 18418 times.
✗ Branch 1 not taken.
18418 timeout = args[0]->val_real();
5978
5979 /*
5980 Report error or warning depending on the value of SQL_MODE.
5981 If SQL is STRICT then report error, else report warning and continue
5982 execution.
5983 */
5984
5985
3/4
✓ Branch 0 taken 18416 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18416 times.
18418 if (args[0]->null_value || timeout < 0) {
5986
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (!thd->lex->is_ignore() && thd->is_strict_mode()) {
5987
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_WRONG_ARGUMENTS, MYF(0), "sleep.");
5988 1 return 0;
5989 } else
5990
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 push_warning_printf(thd, Sql_condition::SL_WARNING, ER_WRONG_ARGUMENTS,
5991 ER_THD(thd, ER_WRONG_ARGUMENTS), "sleep.");
5992 }
5993 /*
5994 On 64-bit OSX mysql_cond_timedwait() waits forever
5995 if passed abstime time has already been exceeded by
5996 the system time.
5997 When given a very short timeout (< 10 mcs) just return
5998 immediately.
5999 We assume that the lines between this test and the call
6000 to mysql_cond_timedwait() will be executed in less than 0.00001 sec.
6001 */
6002
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 18404 times.
18417 if (timeout < 0.00001) return 0;
6003
6004
1/2
✓ Branch 0 taken 18404 times.
✗ Branch 1 not taken.
18404 timed_cond.set_timeout((ulonglong)(timeout * 1000000000.0));
6005
6006
1/2
✓ Branch 0 taken 18404 times.
✗ Branch 1 not taken.
18404 mysql_cond_init(key_item_func_sleep_cond, &cond);
6007
1/2
✓ Branch 0 taken 18403 times.
✗ Branch 1 not taken.
18404 mysql_mutex_lock(&LOCK_item_func_sleep);
6008
6009
1/2
✓ Branch 0 taken 18403 times.
✗ Branch 1 not taken.
18403 thd->ENTER_COND(&cond, &LOCK_item_func_sleep, &stage_user_sleep, nullptr);
6010
6011
3/6
✓ Branch 0 taken 18403 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18403 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18403 times.
✗ Branch 5 not taken.
18403 DEBUG_SYNC(current_thd, "func_sleep_before_sleep");
6012
6013 18403 error = 0;
6014
1/2
✓ Branch 0 taken 18403 times.
✗ Branch 1 not taken.
18403 thd_wait_begin(thd, THD_WAIT_SLEEP);
6015
2/2
✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 31 times.
18434 while (!thd->killed) {
6016
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18403 error = timed_cond.wait(&cond, &LOCK_item_func_sleep);
6017
2/2
✓ Branch 0 taken 18345 times.
✓ Branch 1 taken 31 times.
18376 if (is_timeout(error)) break;
6018 31 error = 0;
6019 }
6020
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18376 thd_wait_end(thd);
6021
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18376 mysql_mutex_unlock(&LOCK_item_func_sleep);
6022
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18376 thd->EXIT_COND(nullptr);
6023
6024
1/2
✓ Branch 0 taken 18376 times.
✗ Branch 1 not taken.
18376 mysql_cond_destroy(&cond);
6025
6026 18376 return (error == 0); // Return 1 killed
6027 }
6028
6029 /**
6030 Get variable with given name; conditionally create it if non-existing
6031
6032 @param thd thread context
6033 @param name name of user variable
6034 @param cs character set;
6035 = NULL: Do not create variable if non-existing.
6036 != NULL: Create variable with this character set.
6037
6038 @returns pointer to variable entry.
6039 = NULL: variable does not exist (if cs == NULL), or
6040 could not create variable (if cs != NULL)
6041 */
6042 3545537 static user_var_entry *get_variable(THD *thd, const Name_string &name,
6043 const CHARSET_INFO *cs) {
6044
1/2
✓ Branch 0 taken 3545540 times.
✗ Branch 1 not taken.
3545537 const std::string key(name.ptr(), name.length());
6045
6046 /* Protects thd->user_vars. */
6047 3545541 mysql_mutex_assert_owner(&thd->LOCK_thd_data);
6048
6049
1/2
✓ Branch 0 taken 3545539 times.
✗ Branch 1 not taken.
3545548 user_var_entry *entry = find_or_nullptr(thd->user_vars, key);
6050
4/4
✓ Branch 0 taken 197599 times.
✓ Branch 1 taken 3347940 times.
✓ Branch 2 taken 180845 times.
✓ Branch 3 taken 16754 times.
3545539 if (entry == nullptr && cs != nullptr) {
6051
1/2
✓ Branch 0 taken 180845 times.
✗ Branch 1 not taken.
180845 entry = user_var_entry::create(thd, name, cs);
6052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180845 times.
180845 if (entry == nullptr) return nullptr;
6053
1/2
✓ Branch 0 taken 180844 times.
✗ Branch 1 not taken.
180845 thd->user_vars.emplace(
6054 361689 key, unique_ptr_with_deleter<user_var_entry>(entry, &free_user_var));
6055 }
6056 3545539 return entry;
6057 3545539 }
6058
6059 981947 void Item_func_set_user_var::cleanup() {
6060 981947 Item_func::cleanup();
6061 /*
6062 Ensure that a valid user variable object is rebound on next
6063 execution. This is important if the user variable is referenced by a
6064 trigger: the trigger references an Item_func_set_user_var, and may be
6065 used by another THD in the future (the trigger is cached in a TABLE). When
6066 that later happens, the other THD will use the same Item_func_set_user_var
6067 but shouldn't try to access the previous THD's entry. So we clear it here,
6068 and set it again later in Item_func_set_user_var::update().
6069 */
6070 981949 entry = nullptr;
6071 981949 }
6072
6073 1644101 bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists) {
6074
2/2
✓ Branch 0 taken 1641559 times.
✓ Branch 1 taken 2542 times.
1644101 if (entry == nullptr) {
6075 const CHARSET_INFO *cs =
6076 create_if_not_exists
6077
2/2
✓ Branch 0 taken 1636737 times.
✓ Branch 1 taken 4822 times.
3278297 ? (args[0]->collation.derivation == DERIVATION_NUMERIC
6078
2/2
✓ Branch 0 taken 1117374 times.
✓ Branch 1 taken 519363 times.
1636737 ? default_charset()
6079 519363 : args[0]->collation.collation)
6080 1641560 : nullptr;
6081
6082 /* Protects thd->user_vars. */
6083 1641560 mysql_mutex_lock(&thd->LOCK_thd_data);
6084 1641561 entry = get_variable(thd, name, cs);
6085 1641558 mysql_mutex_unlock(&thd->LOCK_thd_data);
6086
6087
2/2
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 1641158 times.
1641561 if (entry == nullptr) return true;
6088 }
6089
6090 // Ensure this user variable is owned by the current session
6091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1643698 times.
1643700 assert(entry->owner_session() == thd);
6092
6093 1643698 return false;
6094 }
6095
6096 /*
6097 When a user variable is updated (in a SET command or a query like
6098 SELECT @a:= ).
6099 */
6100
6101 660412 bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) {
6102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660412 times.
660412 assert(!fixed);
6103
6104
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 660213 times.
660412 if (Item_func::fix_fields(thd, ref)) return true;
6105
6106 // This is probably only to get an early validity check on user variable name
6107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660212 times.
660213 if (set_entry(thd, true)) return true;
6108 660212 entry = nullptr;
6109
6110 660212 null_item = (args[0]->type() == NULL_ITEM);
6111
6112 660213 return false;
6113 }
6114
6115 660213 bool Item_func_set_user_var::resolve_type(THD *thd) {
6116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 660213 times.
660213 if (Item_var_func::resolve_type(thd)) return true;
6117 660213 set_nullable(args[0]->is_nullable());
6118 660213 collation.set(DERIVATION_IMPLICIT);
6119 /*
6120 this sets the character set of the item immediately; rules for the
6121 character set of the variable ("entry" object) are different: if "entry"
6122 did not exist previously, set_entry () has created it and has set its
6123 character set; but if it existed previously, it keeps its previous
6124 character set, which may change only when we are sure that the assignment
6125 is to be executed, i.e. in user_var_entry::store ().
6126 */
6127
2/2
✓ Branch 0 taken 443331 times.
✓ Branch 1 taken 216882 times.
660213 if (args[0]->collation.derivation == DERIVATION_NUMERIC)
6128 443331 collation.collation = default_charset();
6129 else
6130 216882 collation.collation = args[0]->collation.collation;
6131
6132 660213 enum_field_types type = Item::type_for_variable(args[0]->data_type());
6133
4/5
✓ Branch 0 taken 425820 times.
✓ Branch 1 taken 3251 times.
✓ Branch 2 taken 14106 times.
✓ Branch 3 taken 217036 times.
✗ Branch 4 not taken.
660213 switch (type) {
6134 425820 case MYSQL_TYPE_LONGLONG:
6135 425820 set_data_type_longlong();
6136 425820 unsigned_flag = args[0]->unsigned_flag;
6137 425820 max_length =
6138 425820 args[0]->max_length; // Preserves "length" of integer constants
6139 425820 break;
6140 3251 case MYSQL_TYPE_NEWDECIMAL:
6141 3251 set_data_type_decimal(args[0]->decimal_precision(), args[0]->decimals);
6142 3251 break;
6143 14106 case MYSQL_TYPE_DOUBLE:
6144 14106 set_data_type_double();
6145 14106 break;
6146 217036 case MYSQL_TYPE_VARCHAR:
6147 217036 set_data_type_string(args[0]->max_char_length());
6148 217036 break;
6149 case MYSQL_TYPE_NULL:
6150 default:
6151 assert(false);
6152 set_data_type(MYSQL_TYPE_NULL);
6153 break;
6154 }
6155
6156 660213 cached_result_type = Item::type_to_result(data_type());
6157
6158 660213 return false;
6159 }
6160
6161 // static
6162 180845 user_var_entry *user_var_entry::create(THD *thd, const Name_string &name,
6163 const CHARSET_INFO *cs) {
6164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180845 times.
180845 if (check_column_name(name.ptr())) {
6165 my_error(ER_ILLEGAL_USER_VAR, MYF(0), name.ptr());
6166 return nullptr;
6167 }
6168
6169 user_var_entry *entry;
6170 size_t size =
6171 180845 ALIGN_SIZE(sizeof(user_var_entry)) + (name.length() + 1) + extra_size;
6172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180845 times.
180845 if (!(entry = (user_var_entry *)my_malloc(key_memory_user_var_entry, size,
6173 MYF(MY_WME | ME_FATALERROR))))
6174 return nullptr;
6175 180845 entry->init(thd, name, cs);
6176 180845 return entry;
6177 }
6178
6179 3376577 bool user_var_entry::mem_realloc(size_t length) {
6180
2/2
✓ Branch 0 taken 3075365 times.
✓ Branch 1 taken 301212 times.
3376577 if (length <= extra_size) {
6181 /* Enough space to store value in value struct */
6182 3075365 free_value();
6183 3075368 m_ptr = internal_buffer_ptr();
6184 } else {
6185 /* Allocate an external buffer */
6186
2/2
✓ Branch 0 taken 297175 times.
✓ Branch 1 taken 4037 times.
301212 if (m_length != length) {
6187
2/2
✓ Branch 0 taken 8499 times.
✓ Branch 1 taken 288676 times.
297175 if (m_ptr == internal_buffer_ptr()) m_ptr = nullptr;
6188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297175 times.
297175 if (!(m_ptr = (char *)my_realloc(
6189 297175 key_memory_user_var_entry_value, m_ptr, length,
6190 MYF(MY_ALLOW_ZERO_PTR | MY_WME | ME_FATALERROR))))
6191 return true;
6192 }
6193 }
6194 3376580 return false;
6195 }
6196
6197 180845 void user_var_entry::init(THD *thd, const Simple_cstring &name,
6198 const CHARSET_INFO *cs) {
6199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180845 times.
180845 assert(thd != nullptr);
6200 180845 m_owner = thd;
6201 180845 copy_name(name);
6202 180845 reset_value();
6203 180845 m_used_query_id = 0;
6204 180845 collation.set(cs, DERIVATION_IMPLICIT, 0);
6205 180845 unsigned_flag = false;
6206 180845 m_type = STRING_RESULT;
6207 180845 }
6208
6209 3376577 bool user_var_entry::store(const void *from, size_t length, Item_result type) {
6210 3376577 assert_locked();
6211
6212 // Store strings with end \0
6213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3376580 times.
3376580 if (mem_realloc(length + (type == STRING_RESULT))) return true;
6214
2/2
✓ Branch 0 taken 353305 times.
✓ Branch 1 taken 3023275 times.
3376580 if (type == STRING_RESULT) m_ptr[length] = 0; // Store end \0
6215
6216 // Avoid memcpy of a my_decimal object, use copy CTOR instead.
6217
2/2
✓ Branch 0 taken 2574 times.
✓ Branch 1 taken 3374006 times.
3376580 if (type == DECIMAL_RESULT) {
6218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2574 times.
2574 assert(length == sizeof(my_decimal));
6219 2574 const my_decimal *dec = static_cast<const my_decimal *>(from);
6220 2574 dec->sanity_check();
6221
1/2
✓ Branch 0 taken 2574 times.
✗ Branch 1 not taken.
2574 new (m_ptr) my_decimal(*dec);
6222 } else
6223 3374006 memcpy(m_ptr, from, length);
6224
6225 3376580 m_length = length;
6226 3376580 m_type = type;
6227
6228 3376580 set_used_query_id(current_thd->query_id);
6229
6230 3376576 return false;
6231 }
6232
6233 6937272 void user_var_entry::assert_locked() const {
6234 6937272 mysql_mutex_assert_owner(&m_owner->LOCK_thd_data);
6235 6937282 }
6236
6237 3376577 bool user_var_entry::store(const void *ptr, size_t length, Item_result type,
6238 const CHARSET_INFO *cs, Derivation dv,
6239 bool unsigned_arg) {
6240 3376577 assert_locked();
6241
6242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3376576 times.
3376579 if (store(ptr, length, type)) return true;
6243 3376576 collation.set(cs, dv);
6244 3376574 unsigned_flag = unsigned_arg;
6245 3376574 return false;
6246 }
6247
6248 3380129 void user_var_entry::lock() {
6249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3380129 times.
3380129 assert(m_owner != nullptr);
6250 3380129 mysql_mutex_lock(&m_owner->LOCK_thd_data);
6251 3380132 }
6252
6253 3380129 void user_var_entry::unlock() {
6254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3380129 times.
3380129 assert(m_owner != nullptr);
6255 3380129 mysql_mutex_unlock(&m_owner->LOCK_thd_data);
6256 3380133 }
6257
6258 3379269 bool Item_func_set_user_var::update_hash(const void *ptr, uint length,
6259 Item_result res_type,
6260 const CHARSET_INFO *cs, Derivation dv,
6261 bool unsigned_arg) {
6262 3379269 entry->lock();
6263
6264 // args[0]->null_value could be outdated
6265
2/2
✓ Branch 0 taken 27318 times.
✓ Branch 1 taken 3351953 times.
3379272 if (args[0]->type() == Item::FIELD_ITEM)
6266 27318 null_value = ((Item_field *)args[0])->field->is_null();
6267 else
6268 3351953 null_value = args[0]->null_value;
6269
6270
2/2
✓ Branch 0 taken 2559 times.
✓ Branch 1 taken 3376712 times.
3379271 if (ptr == nullptr) {
6271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2559 times.
2559 assert(length == 0);
6272 2559 null_value = true;
6273 }
6274
6275 /*
6276 If we set a variable explicitly to NULL then keep the old
6277 result type of the variable
6278 */
6279
4/4
✓ Branch 0 taken 3529 times.
✓ Branch 1 taken 3375742 times.
✓ Branch 2 taken 842 times.
✓ Branch 3 taken 2687 times.
3379271 if (null_value && null_item) res_type = entry->type();
6280
6281
2/2
✓ Branch 0 taken 3529 times.
✓ Branch 1 taken 3375741 times.
3379270 if (null_value)
6282 3529 entry->set_null_value(res_type);
6283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3375739 times.
3375741 else if (entry->store(ptr, length, res_type, cs, dv, unsigned_arg)) {
6284 entry->unlock();
6285 null_value = true;
6286 return true;
6287 }
6288 3379268 entry->unlock();
6289 3379273 return false;
6290 }
6291
6292 /** Get the value of a variable as a double. */
6293
6294 580421 double user_var_entry::val_real(bool *null_value) const {
6295
2/2
✓ Branch 0 taken 203 times.
✓ Branch 1 taken 580218 times.
580421 if ((*null_value = (m_ptr == nullptr))) return 0.0;
6296
6297
4/6
✓ Branch 0 taken 83631 times.
✓ Branch 1 taken 490714 times.
✓ Branch 2 taken 1227 times.
✓ Branch 3 taken 4646 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
580218 switch (m_type) {
6298 83631 case REAL_RESULT:
6299 83631 return *reinterpret_cast<double *>(m_ptr);
6300 490714 case INT_RESULT:
6301
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 490709 times.
490714 if (unsigned_flag)
6302 5 return static_cast<double>(*reinterpret_cast<ulonglong *>(m_ptr));
6303 else
6304 490709 return static_cast<double>(*reinterpret_cast<longlong *>(m_ptr));
6305 1227 case DECIMAL_RESULT: {
6306 double result;
6307
1/2
✓ Branch 0 taken 1227 times.
✗ Branch 1 not taken.
1227 my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)m_ptr, &result);
6308 1227 return result;
6309 }
6310 4646 case STRING_RESULT:
6311 9292 return double_from_string_with_check(collation.collation, m_ptr,
6312 4646 m_ptr + m_length);
6313 case ROW_RESULT:
6314 case INVALID_RESULT:
6315 assert(false); // Impossible
6316 break;
6317 }
6318 return 0.0; // Impossible
6319 }
6320
6321 /** Get the value of a variable as an integer. */
6322
6323 5650186 longlong user_var_entry::val_int(bool *null_value) const {
6324
2/2
✓ Branch 0 taken 1177 times.
✓ Branch 1 taken 5649009 times.
5650186 if ((*null_value = (m_ptr == nullptr))) return 0LL;
6325
6326
4/6
✓ Branch 0 taken 112058 times.
✓ Branch 1 taken 5532799 times.
✓ Branch 2 taken 4089 times.
✓ Branch 3 taken 63 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
5649009 switch (m_type) {
6327 112058 case REAL_RESULT: {
6328 // TODO(tdidriks): Consider reporting a possible overflow warning.
6329 112058 double var_val = *(reinterpret_cast<double *>(m_ptr));
6330 longlong res;
6331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112058 times.
112058 if (var_val <= LLONG_MIN) {
6332 res = LLONG_MIN;
6333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112058 times.
112058 } else if (var_val >= LLONG_MAX_DOUBLE) {
6334 res = LLONG_MAX;
6335 } else
6336 112058 res = var_val;
6337
6338 112058 return res;
6339 }
6340 5532799 case INT_RESULT:
6341 5532799 return *(longlong *)m_ptr;
6342 4089 case DECIMAL_RESULT: {
6343 longlong result;
6344
1/2
✓ Branch 0 taken 4089 times.
✗ Branch 1 not taken.
4089 my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)m_ptr, false, &result);
6345 4089 return result;
6346 }
6347 63 case STRING_RESULT: {
6348 int error;
6349
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 return my_strtoll10(m_ptr, nullptr,
6350 63 &error); // String is null terminated
6351 }
6352 case ROW_RESULT:
6353 case INVALID_RESULT:
6354 assert(false); // Impossible
6355 break;
6356 }
6357 return 0LL; // Impossible
6358 }
6359
6360 /** Get the value of a variable as a string. */
6361
6362 1867073 String *user_var_entry::val_str(bool *null_value, String *str,
6363 uint decimals) const {
6364
2/2
✓ Branch 0 taken 4124 times.
✓ Branch 1 taken 1862949 times.
1867073 if ((*null_value = (m_ptr == nullptr))) return (String *)nullptr;
6365
6366
4/6
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 45797 times.
✓ Branch 2 taken 265 times.
✓ Branch 3 taken 1816825 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1862949 switch (m_type) {
6367 62 case REAL_RESULT:
6368 62 str->set_real(*(double *)m_ptr, decimals, collation.collation);
6369 62 break;
6370 45797 case INT_RESULT:
6371
2/2
✓ Branch 0 taken 45572 times.
✓ Branch 1 taken 225 times.
45797 if (!unsigned_flag)
6372 45572 str->set(*(longlong *)m_ptr, collation.collation);
6373 else
6374 225 str->set(*(ulonglong *)m_ptr, collation.collation);
6375 45797 break;
6376 265 case DECIMAL_RESULT:
6377 265 str_set_decimal(E_DEC_FATAL_ERROR, pointer_cast<my_decimal *>(m_ptr), str,
6378 265 collation.collation, decimals);
6379 265 break;
6380 1816825 case STRING_RESULT:
6381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1816827 times.
1816825 if (str->copy(m_ptr, m_length, collation.collation))
6382 str = nullptr; // EOM error
6383 1816827 break;
6384 case ROW_RESULT:
6385 case INVALID_RESULT:
6386 assert(false); // Impossible
6387 break;
6388 }
6389 1862951 return (str);
6390 }
6391
6392 /** Get the value of a variable as a decimal. */
6393
6394 1821 my_decimal *user_var_entry::val_decimal(bool *null_value,
6395 my_decimal *val) const {
6396
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 1684 times.
1821 if ((*null_value = (m_ptr == nullptr))) return nullptr;
6397
6398
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 1631 times.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1684 switch (m_type) {
6399 1 case REAL_RESULT:
6400 1 double2my_decimal(E_DEC_FATAL_ERROR, *(double *)m_ptr, val);
6401 1 break;
6402 43 case INT_RESULT:
6403 43 int2my_decimal(E_DEC_FATAL_ERROR, *pointer_cast<longlong *>(m_ptr),
6404 43 unsigned_flag, val);
6405 43 break;
6406 1631 case DECIMAL_RESULT:
6407 1631 my_decimal2decimal(reinterpret_cast<my_decimal *>(m_ptr), val);
6408 1631 break;
6409 9 case STRING_RESULT:
6410 9 str2my_decimal(E_DEC_FATAL_ERROR, m_ptr, m_length, collation.collation,
6411 val);
6412 9 break;
6413 case ROW_RESULT:
6414 case INVALID_RESULT:
6415 assert(false); // Impossible
6416 break;
6417 }
6418 1684 return (val);
6419 }
6420
6421 /**
6422 This functions is invoked on SET \@variable or
6423 \@variable:= expression.
6424
6425 Evaluate (and check expression), store results.
6426
6427 @note
6428 For now it always return OK. All problem with value evaluating
6429 will be caught by thd->is_error() check in sql_set_variables().
6430
6431 @retval
6432 false OK.
6433 */
6434
6435 3199194 bool Item_func_set_user_var::check(bool use_result_field) {
6436
1/2
✓ Branch 0 taken 3199198 times.
✗ Branch 1 not taken.
3199194 DBUG_TRACE;
6437
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 3199194 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
3199198 if (use_result_field && !result_field) use_result_field = false;
6438
6439
5/5
✓ Branch 0 taken 92269 times.
✓ Branch 1 taken 2765805 times.
✓ Branch 2 taken 338762 times.
✓ Branch 3 taken 2360 times.
✓ Branch 4 taken 2 times.
3199198 switch (cached_result_type) {
6440 92269 case REAL_RESULT: {
6441 92269 save_result.vreal =
6442
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 92269 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 92269 times.
✗ Branch 5 not taken.
92269 use_result_field ? result_field->val_real() : args[0]->val_real();
6443 92269 break;
6444 }
6445 2765805 case INT_RESULT: {
6446 2765804 save_result.vint =
6447
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2765805 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2765804 times.
✗ Branch 5 not taken.
2765805 use_result_field ? result_field->val_int() : args[0]->val_int();
6448
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2765804 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2765804 unsigned_flag = use_result_field ? result_field->is_unsigned()
6449 2765804 : args[0]->unsigned_flag;
6450 2765804 break;
6451 }
6452 338762 case STRING_RESULT: {
6453
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 338758 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
338762 save_result.vstr = use_result_field ? result_field->val_str(&value)
6454
1/2
✓ Branch 0 taken 338759 times.
✗ Branch 1 not taken.
338758 : args[0]->val_str(&value);
6455 338763 break;
6456 }
6457 2360 case DECIMAL_RESULT: {
6458 2360 save_result.vdec = use_result_field
6459
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2360 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2360 ? result_field->val_decimal(&decimal_buff)
6460
1/2
✓ Branch 0 taken 2360 times.
✗ Branch 1 not taken.
2360 : args[0]->val_decimal(&decimal_buff);
6461 2360 break;
6462 }
6463 2 case ROW_RESULT:
6464 default:
6465 // This case should never be chosen
6466 2 assert(0);
6467 break;
6468 }
6469 3199196 return false;
6470 3199196 }
6471
6472 /**
6473 @brief Evaluate and store item's result.
6474 This function is invoked on "SELECT ... INTO @var ...".
6475
6476 @param item An item to get value from.
6477 */
6478
6479 173375 void Item_func_set_user_var::save_item_result(Item *item) {
6480
1/2
✓ Branch 0 taken 173375 times.
✗ Branch 1 not taken.
173375 DBUG_TRACE;
6481
6482
4/5
✓ Branch 0 taken 11708 times.
✓ Branch 1 taken 149880 times.
✓ Branch 2 taken 10678 times.
✓ Branch 3 taken 1109 times.
✗ Branch 4 not taken.
173375 switch (cached_result_type) {
6483 11708 case REAL_RESULT:
6484
1/2
✓ Branch 0 taken 11708 times.
✗ Branch 1 not taken.
11708 save_result.vreal = item->val_real();
6485 11708 break;
6486 149880 case INT_RESULT:
6487
1/2
✓ Branch 0 taken 149880 times.
✗ Branch 1 not taken.
149880 save_result.vint = item->val_int();
6488 149880 unsigned_flag = item->unsigned_flag;
6489 149880 break;
6490 10678 case STRING_RESULT:
6491
1/2
✓ Branch 0 taken 10678 times.
✗ Branch 1 not taken.
10678 save_result.vstr = item->val_str(&value);
6492 10678 break;
6493 1109 case DECIMAL_RESULT:
6494
1/2
✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
1109 save_result.vdec = item->val_decimal(&decimal_buff);
6495 1109 break;
6496 case ROW_RESULT:
6497 default:
6498 // Should never happen
6499 assert(0);
6500 break;
6501 }
6502 173375 }
6503
6504 /**
6505 Update user variable from value in save_result
6506
6507 @returns false if success, true when error (EOM)
6508 */
6509
6510 3372523 bool Item_func_set_user_var::update() {
6511
1/2
✓ Branch 0 taken 3372527 times.
✗ Branch 1 not taken.
3372523 DBUG_TRACE;
6512
6513 // Ensure that a user variable object is bound for each execution.
6514
6/10
✓ Branch 0 taken 972317 times.
✓ Branch 1 taken 2400210 times.
✓ Branch 2 taken 972317 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 972317 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 972317 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3372527 times.
3372527 if (entry == nullptr && set_entry(current_thd, true)) return true;
6515
6516 3372527 bool res = false;
6517
6518
5/5
✓ Branch 0 taken 103976 times.
✓ Branch 1 taken 2915672 times.
✓ Branch 2 taken 349408 times.
✓ Branch 3 taken 3469 times.
✓ Branch 4 taken 2 times.
3372527 switch (cached_result_type) {
6519 103976 case REAL_RESULT: {
6520
2/4
✓ Branch 0 taken 103976 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 103976 times.
✗ Branch 3 not taken.
103976 res = update_hash(&save_result.vreal, sizeof(save_result.vreal),
6521 REAL_RESULT, default_charset(), DERIVATION_IMPLICIT,
6522 false);
6523 103976 break;
6524 }
6525 2915672 case INT_RESULT: {
6526
1/2
✓ Branch 0 taken 2915675 times.
✗ Branch 1 not taken.
2915672 res = update_hash(&save_result.vint, sizeof(save_result.vint), INT_RESULT,
6527
1/2
✓ Branch 0 taken 2915672 times.
✗ Branch 1 not taken.
2915672 default_charset(), DERIVATION_IMPLICIT, unsigned_flag);
6528 2915675 break;
6529 }
6530 349408 case STRING_RESULT: {
6531
2/2
✓ Branch 0 taken 1615 times.
✓ Branch 1 taken 347793 times.
349408 if (!save_result.vstr) // Null value
6532
1/2
✓ Branch 0 taken 1615 times.
✗ Branch 1 not taken.
1615 res = update_hash(nullptr, 0, STRING_RESULT, &my_charset_bin,
6533 DERIVATION_IMPLICIT, false);
6534 else
6535
1/2
✓ Branch 0 taken 347794 times.
✗ Branch 1 not taken.
347793 res = update_hash(save_result.vstr->ptr(), save_result.vstr->length(),
6536 347793 STRING_RESULT, save_result.vstr->charset(),
6537 DERIVATION_IMPLICIT, false);
6538 349409 break;
6539 }
6540 3469 case DECIMAL_RESULT: {
6541
2/2
✓ Branch 0 taken 902 times.
✓ Branch 1 taken 2567 times.
3469 if (!save_result.vdec) // Null value
6542
1/2
✓ Branch 0 taken 902 times.
✗ Branch 1 not taken.
902 res = update_hash(nullptr, 0, DECIMAL_RESULT, &my_charset_bin,
6543 DERIVATION_IMPLICIT, false);
6544 else
6545
2/4
✓ Branch 0 taken 2567 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2567 times.
✗ Branch 3 not taken.
2567 res = update_hash(save_result.vdec, sizeof(my_decimal), DECIMAL_RESULT,
6546 default_charset(), DERIVATION_IMPLICIT, false);
6547 3469 break;
6548 }
6549 2 case ROW_RESULT:
6550 default:
6551 // This case should never be chosen
6552 2 assert(0);
6553 break;
6554 }
6555 3372529 return res;
6556 3372529 }
6557
6558 169 double Item_func_set_user_var::val_real() {
6559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 169 times.
169 assert(fixed == 1);
6560 169 check(false);
6561 169 update(); // Store expression
6562 169 return entry->val_real(&null_value);
6563 }
6564
6565 107912 longlong Item_func_set_user_var::val_int() {
6566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107912 times.
107912 assert(fixed == 1);
6567 107912 check(false);
6568 107912 update(); // Store expression
6569 107912 return entry->val_int(&null_value);
6570 }
6571
6572 32594 String *Item_func_set_user_var::val_str(String *str) {
6573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32594 times.
32594 assert(fixed == 1);
6574 32594 check(false);
6575 32594 update(); // Store expression
6576 32594 return entry->val_str(&null_value, str, decimals);
6577 }
6578
6579 14 my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val) {
6580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 assert(fixed == 1);
6581 14 check(false);
6582 14 update(); // Store expression
6583 14 return entry->val_decimal(&null_value, val);
6584 }
6585
6586 // just the assignment, for use in "SET @a:=5" type self-prints
6587 19 void Item_func_set_user_var::print_assignment(
6588 const THD *thd, String *str, enum_query_type query_type) const {
6589 19 str->append(STRING_WITH_LEN("@"));
6590 19 str->append(name);
6591 19 str->append(STRING_WITH_LEN(":="));
6592 19 args[0]->print(thd, str, query_type);
6593 19 }
6594
6595 // parenthesize assignment for use in "EXPLAIN EXTENDED SELECT (@e:=80)+5"
6596 19 void Item_func_set_user_var::print(const THD *thd, String *str,
6597 enum_query_type query_type) const {
6598 19 str->append(STRING_WITH_LEN("("));
6599 19 print_assignment(thd, str, query_type);
6600 19 str->append(STRING_WITH_LEN(")"));
6601 19 }
6602
6603 8701 bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg) {
6604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8701 times.
8701 if (result_field) {
6605 check(true);
6606 update();
6607 /*
6608 TODO This func have to be changed to avoid sending data as a field.
6609 */
6610 return protocol->store_field(result_field);
6611 }
6612 8701 return Item::send(protocol, str_arg);
6613 }
6614
6615 2838 void Item_func_set_user_var::make_field(Send_field *tmp_field) {
6616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2838 times.
2838 if (result_field) {
6617 result_field->make_send_field(tmp_field);
6618 assert(tmp_field->table_name != nullptr);
6619 if (Item::item_name.is_set())
6620 tmp_field->col_name = Item::item_name.ptr(); // Use user supplied name
6621 } else
6622 2838 Item::make_field(tmp_field);
6623 2838 }
6624
6625 /*
6626 Save the value of a user variable into a field
6627
6628 SYNOPSIS
6629 save_in_field()
6630 field target field to save the value to
6631 no_conversion flag indicating whether conversions are allowed
6632
6633 DESCRIPTION
6634 Save the function value into a field and update the user variable
6635 accordingly. If a result field is defined and the target field doesn't
6636 coincide with it then the value from the result field will be used as
6637 the new value of the user variable.
6638
6639 The reason to have this method rather than simply using the result
6640 field in the val_xxx() methods is that the value from the result field
6641 not always can be used when the result field is defined.
6642 Let's consider the following cases:
6643 1) when filling a tmp table the result field is defined but the value of it
6644 is undefined because it has to be produced yet. Thus we can't use it.
6645 2) on execution of an INSERT ... SELECT statement the save_in_field()
6646 function will be called to fill the data in the new record. If the SELECT
6647 part uses a tmp table then the result field is defined and should be
6648 used in order to get the correct result.
6649
6650 The difference between the SET_USER_VAR function and regular functions
6651 like CONCAT is that the Item_func objects for the regular functions are
6652 replaced by Item_field objects after the values of these functions have
6653 been stored in a tmp table. Yet an object of the Item_field class cannot
6654 be used to update a user variable.
6655 Due to this we have to handle the result field in a special way here and
6656 in the Item_func_set_user_var::send() function.
6657
6658 RETURN VALUES
6659 TYPE_OK Ok
6660 Everything else Error
6661 */
6662
6663 2262886 type_conversion_status Item_func_set_user_var::save_in_field(
6664 Field *field, bool no_conversions, bool can_use_result_field) {
6665 2262886 bool use_result_field =
6666
5/6
✓ Branch 0 taken 2262886 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45342 times.
✓ Branch 3 taken 2217544 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 45338 times.
2262886 (!can_use_result_field ? 0 : (result_field && result_field != field));
6667 type_conversion_status error;
6668
6669 /* Update the value of the user variable */
6670 2262886 check(use_result_field);
6671 2262886 update();
6672
6673
4/4
✓ Branch 0 taken 2212847 times.
✓ Branch 1 taken 50039 times.
✓ Branch 2 taken 50049 times.
✓ Branch 3 taken 2212837 times.
4475733 if (result_type() == STRING_RESULT ||
6674
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 2212819 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 18 times.
2212847 (result_type() == REAL_RESULT && field->result_type() == STRING_RESULT)) {
6675 String *result;
6676 50049 const CHARSET_INFO *cs = collation.collation;
6677 char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
6678 50049 str_value.set_quick(buff, sizeof(buff), cs);
6679
1/2
✓ Branch 0 taken 50049 times.
✗ Branch 1 not taken.
50049 result = entry->val_str(&null_value, &str_value, decimals);
6680
6681
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 50047 times.
50049 if (null_value) {
6682 2 str_value.set_quick(nullptr, 0, cs);
6683
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 return set_field_to_null_with_conversions(field, no_conversions);
6684 }
6685
6686 /* NOTE: If null_value == false, "result" must be not NULL. */
6687
6688
1/2
✓ Branch 0 taken 50047 times.
✗ Branch 1 not taken.
50047 field->set_notnull();
6689
1/2
✓ Branch 0 taken 50047 times.
✗ Branch 1 not taken.
50047 error = field->store(result->ptr(), result->length(), cs);
6690 50047 str_value.set_quick(nullptr, 0, cs);
6691
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2212819 times.
2212837 } else if (result_type() == REAL_RESULT) {
6692 18 double nr = entry->val_real(&null_value);
6693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (null_value) return set_field_to_null(field);
6694 18 field->set_notnull();
6695 18 error = field->store(nr);
6696
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2212810 times.
2212819 } else if (result_type() == DECIMAL_RESULT) {
6697 9 my_decimal decimal_value;
6698
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 my_decimal *val = entry->val_decimal(&null_value, &decimal_value);
6699
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 if (null_value) return set_field_to_null(field);
6700
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 field->set_notnull();
6701
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 error = field->store_decimal(val);
6702
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 } else {
6703 2212810 longlong nr = entry->val_int(&null_value);
6704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2212810 times.
2212810 if (null_value)
6705 return set_field_to_null_with_conversions(field, no_conversions);
6706 2212810 field->set_notnull();
6707 2212810 error = field->store(nr, unsigned_flag);
6708 }
6709 2262884 return error;
6710 }
6711
6712 1744398 String *Item_func_get_user_var::val_str(String *str) {
6713
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1744398 times.
1744398 assert(fixed);
6714
1/2
✓ Branch 0 taken 1744400 times.
✗ Branch 1 not taken.
1744398 DBUG_TRACE;
6715
1/2
✓ Branch 0 taken 1744400 times.
✗ Branch 1 not taken.
1744400 THD *thd = current_thd;
6716
3/4
✓ Branch 0 taken 414932 times.
✓ Branch 1 taken 1329468 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1744401 times.
2159333 if (var_entry == nullptr &&
6717
2/4
✓ Branch 0 taken 414933 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 414933 times.
414932 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6718 return error_str();
6719
3/4
✓ Branch 0 taken 370 times.
✓ Branch 1 taken 1744031 times.
✓ Branch 2 taken 370 times.
✗ Branch 3 not taken.
1744401 if (var_entry == nullptr) return error_str(); // No such variable
6720
1/2
✓ Branch 0 taken 1744030 times.
✗ Branch 1 not taken.
1744031 String *res = var_entry->val_str(&null_value, str, decimals);
6721
7/8
✓ Branch 0 taken 1740281 times.
✓ Branch 1 taken 3749 times.
✓ Branch 2 taken 1740279 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2582 times.
✓ Branch 5 taken 1737697 times.
✓ Branch 6 taken 2582 times.
✓ Branch 7 taken 1741446 times.
1744030 if (res && !my_charset_same(res->charset(), collation.collation)) {
6722 2582 String tmpstr;
6723 uint error;
6724
1/2
✓ Branch 0 taken 2582 times.
✗ Branch 1 not taken.
2582 if (tmpstr.copy(res->ptr(), res->length(), res->charset(),
6725
2/4
✓ Branch 0 taken 2582 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2582 times.
5164 collation.collation, &error) ||
6726
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2582 times.
2582 error > 0) {
6727 char tmp[32];
6728 convert_to_printable(tmp, sizeof(tmp), res->ptr(), res->length(),
6729 res->charset(), 6);
6730 my_error(ER_INVALID_CHARACTER_STRING, MYF(0), collation.collation->csname,
6731 tmp);
6732 return error_str();
6733 }
6734
2/6
✓ Branch 0 taken 2582 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2582 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2582 if (str->copy(tmpstr)) return error_str();
6735 2582 return str;
6736 2582 }
6737 1741446 return res;
6738 1744398 }
6739
6740 580245 double Item_func_get_user_var::val_real() {
6741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 580245 times.
580245 assert(fixed);
6742 THD *thd;
6743
4/6
✓ Branch 0 taken 8398 times.
✓ Branch 1 taken 571847 times.
✓ Branch 2 taken 8398 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 580245 times.
588643 if (var_entry == nullptr && (thd = current_thd) &&
6744
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8398 times.
8398 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6745 return 0.0;
6746
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 580234 times.
580245 if (var_entry == nullptr) return 0.0; // No such variable
6747 580234 return (var_entry->val_real(&null_value));
6748 }
6749
6750 1800 my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec) {
6751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1800 times.
1800 assert(fixed);
6752 THD *thd;
6753
4/6
✓ Branch 0 taken 1780 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1780 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1800 times.
3580 if (var_entry == nullptr && (thd = current_thd) &&
6754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1780 times.
1780 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6755 return nullptr;
6756
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1798 times.
1800 if (var_entry == nullptr) return nullptr;
6757 1798 return var_entry->val_decimal(&null_value, dec);
6758 }
6759
6760 3323207 longlong Item_func_get_user_var::val_int() {
6761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3323207 times.
3323207 assert(fixed);
6762 THD *thd;
6763
5/6
✓ Branch 0 taken 823105 times.
✓ Branch 1 taken 2500102 times.
✓ Branch 2 taken 823100 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3323208 times.
4146309 if (var_entry == nullptr && (thd = current_thd) &&
6764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 823102 times.
823100 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6765 return 0LL;
6766
2/2
✓ Branch 0 taken 1359 times.
✓ Branch 1 taken 3321849 times.
3323208 if (var_entry == nullptr) return 0LL; // No such variable
6767 /*
6768 See bug#27969934 NO WARNING WHEN CAST OF USER VARIABLE
6769 TO NUMBER GOES WRONG.
6770 */
6771 3321849 return var_entry->val_int(&null_value);
6772 }
6773
6774 81187 const CHARSET_INFO *Item_func_get_user_var::charset_for_protocol() {
6775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81187 times.
81187 assert(fixed);
6776 THD *thd;
6777 /*
6778 If the query reads the value of the variable's charset it depends on this
6779 variable, so the user var may need to be stored in the binlog: so we call
6780 get_var_with_binlog.
6781 */
6782
4/6
✓ Branch 0 taken 40841 times.
✓ Branch 1 taken 40346 times.
✓ Branch 2 taken 40841 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81187 times.
122028 if (var_entry == nullptr && (thd = current_thd) &&
6783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40841 times.
40841 get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry))
6784 return &my_charset_bin;
6785
2/2
✓ Branch 0 taken 292 times.
✓ Branch 1 taken 80895 times.
81187 if (var_entry == nullptr) return &my_charset_bin; // No such variable
6786 // @todo WL#6570 Should we return collation of Item node or variable entry?
6787
2/2
✓ Branch 0 taken 54081 times.
✓ Branch 1 taken 26814 times.
80895 return result_type() == STRING_RESULT ? collation.collation : &my_charset_bin;
6788 }
6789
6790 /**
6791 Get variable by name and, if necessary, put the record of variable
6792 use into the binary log.
6793
6794 When a user variable is invoked from an update query (INSERT, UPDATE etc),
6795 stores this variable and its value in thd->user_var_events, so that it can be
6796 written to the binlog (will be written just before the query is written, see
6797 log.cc).
6798
6799 @param thd Current session.
6800 @param sql_command The command the variable participates in.
6801 @param name Variable name
6802 @param[out] out_entry variable structure or NULL. The pointer is set
6803 regardless of whether function succeeded or not.
6804
6805 @retval
6806 0 OK
6807 @retval
6808 1 Failed to put appropriate record into binary log
6809
6810 */
6811
6812 1289054 static int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
6813 const Name_string &name,
6814 user_var_entry **out_entry) {
6815 Binlog_user_var_event *user_var_event;
6816 user_var_entry *var_entry;
6817
6818 /* Protects thd->user_vars. */
6819
1/2
✓ Branch 0 taken 1289053 times.
✗ Branch 1 not taken.
1289054 mysql_mutex_lock(&thd->LOCK_thd_data);
6820
1/2
✓ Branch 0 taken 1289054 times.
✗ Branch 1 not taken.
1289053 var_entry = get_variable(thd, name, nullptr);
6821
1/2
✓ Branch 0 taken 1289058 times.
✗ Branch 1 not taken.
1289054 mysql_mutex_unlock(&thd->LOCK_thd_data);
6822
6823 1289058 *out_entry = var_entry;
6824
6825 /*
6826 In cases when this function is called for a sub-statement, we can't
6827 rely on OPTION_BIN_LOG flag in THD::variables.option_bits bitmap
6828 to determine whether binary logging is turned on, as this bit can be
6829 cleared before executing sub-statement. So instead we have to look
6830 at THD::variables::sql_log_bin member.
6831 */
6832
4/4
✓ Branch 0 taken 1229824 times.
✓ Branch 1 taken 59234 times.
✓ Branch 2 taken 1160045 times.
✓ Branch 3 taken 69779 times.
1289058 bool log_on = mysql_bin_log.is_open() && thd->variables.sql_log_bin;
6833
6834 /*
6835 Any reference to user-defined variable which is done from stored
6836 function or trigger affects their execution and the execution of the
6837 calling statement. We must log all such variables even if they are
6838 not involved in table-updating statements.
6839 */
6840
9/10
✓ Branch 0 taken 1160045 times.
✓ Branch 1 taken 129013 times.
✓ Branch 2 taken 1160044 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 970803 times.
✓ Branch 5 taken 189241 times.
✓ Branch 6 taken 963846 times.
✓ Branch 7 taken 6957 times.
✓ Branch 8 taken 1092859 times.
✓ Branch 9 taken 196198 times.
1289058 if (!(log_on && (is_update_query(sql_command) || thd->in_sub_stmt))) return 0;
6841
6842
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 196148 times.
196198 if (var_entry == nullptr) {
6843 /*
6844 If the variable does not exist, it's NULL, but we want to create it so
6845 that it gets into the binlog (if it didn't, the slave could be
6846 influenced by a variable of the same name previously set by another
6847 thread).
6848 We create it like if it had been explicitly set with SET before.
6849 The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
6850 sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
6851 in dispatch_command()). Instead of building a one-element list to pass to
6852 sql_set_variables(), we could instead manually call check() and update();
6853 this would save memory and time; but calling sql_set_variables() makes
6854 one unique place to maintain (sql_set_variables()).
6855
6856 Manipulation with lex is necessary since free_underlaid_joins
6857 is going to release memory belonging to the main query.
6858 */
6859
6860 50 List<set_var_base> tmp_var_list;
6861
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 LEX *sav_lex = thd->lex, lex_tmp;
6862 50 thd->lex = &lex_tmp;
6863
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 lex_start(thd);
6864
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
100 tmp_var_list.push_back(new (thd->mem_root) set_var_user(
6865
3/6
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
150 new Item_func_set_user_var(name, new Item_null())));
6866 /* Create the variable */
6867
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (sql_set_variables(thd, &tmp_var_list, false)) {
6868 thd->lex = sav_lex;
6869 return 1;
6870 }
6871 50 thd->lex = sav_lex;
6872
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mysql_mutex_lock(&thd->LOCK_thd_data);
6873
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 var_entry = get_variable(thd, name, nullptr);
6874
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 mysql_mutex_unlock(&thd->LOCK_thd_data);
6875
6876 50 *out_entry = var_entry;
6877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (var_entry == nullptr) return 1;
6878
5/6
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 169204 times.
✓ Branch 3 taken 26944 times.
✓ Branch 4 taken 26994 times.
✓ Branch 5 taken 169154 times.
365402 } else if (var_entry->used_query_id() == thd->query_id ||
6879
3/4
✓ Branch 0 taken 169204 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 169154 times.
169204 mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id())) {
6880 /*
6881 If this variable was already stored in user_var_events by this query
6882 (because it's used in more than one place in the query), don't store
6883 it.
6884 */
6885 26994 return 0;
6886 }
6887
6888 /*
6889 First we need to store value of var_entry, when the next situation
6890 appears:
6891 > set @a:=1;
6892 > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
6893 We have to write to binlog value @a= 1.
6894
6895 We allocate the user_var_event on user_var_events_alloc pool, not on
6896 the this-statement-execution pool because in SPs user_var_event objects
6897 may need to be valid after current [SP] statement execution pool is
6898 destroyed.
6899 */
6900 169204 size_t size = ALIGN_SIZE(sizeof(Binlog_user_var_event)) + var_entry->length();
6901 169204 if (!(user_var_event =
6902
2/4
✓ Branch 0 taken 169204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 169204 times.
169204 (Binlog_user_var_event *)thd->user_var_events_alloc->Alloc(size)))
6903 return 1;
6904
6905 169204 user_var_event->value =
6906 169204 (char *)user_var_event + ALIGN_SIZE(sizeof(Binlog_user_var_event));
6907 169204 user_var_event->user_var_event = var_entry;
6908 169204 user_var_event->type = var_entry->type();
6909 169204 user_var_event->charset_number = var_entry->collation.collation->number;
6910 169204 user_var_event->unsigned_flag = var_entry->unsigned_flag;
6911
2/2
✓ Branch 0 taken 2746 times.
✓ Branch 1 taken 166458 times.
169204 if (!var_entry->ptr()) {
6912 /* NULL value*/
6913 2746 user_var_event->length = 0;
6914 2746 user_var_event->value = nullptr;
6915 } else {
6916 // Avoid memcpy of a my_decimal object, use copy CTOR instead.
6917 166458 user_var_event->length = var_entry->length();
6918
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 166399 times.
166458 if (user_var_event->type == DECIMAL_RESULT) {
6919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 assert(var_entry->length() == sizeof(my_decimal));
6920 const my_decimal *dec = static_cast<const my_decimal *>(
6921 59 static_cast<const void *>(var_entry->ptr()));
6922 59 dec->sanity_check();
6923
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 new (user_var_event->value) my_decimal(*dec);
6924 } else
6925 166399 memcpy(user_var_event->value, var_entry->ptr(), var_entry->length());
6926 }
6927 // Mark that this variable has been used by this query
6928 169204 var_entry->set_used_query_id(thd->query_id);
6929
2/4
✓ Branch 0 taken 169204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 169204 times.
169204 if (thd->user_var_events.push_back(user_var_event)) return 1;
6930
6931 169204 return 0;
6932 }
6933
6934 614819 bool Item_func_get_user_var::resolve_type(THD *thd) {
6935 614819 set_nullable(true);
6936
6937 /*
6938 @todo WL#6570 change has effects:
6939 - bad: in packet.test (see comment there), ps_<n><engine>.test
6940 (e.g. ps_5merge.test) (see comment in include/ps_conv.inc),
6941 ps_w_max_indexes_64
6942 - good: type_temporal_fractional.test (see comment in that file)
6943 - fixes failure of: sysschema.pr_statement_performance_analyzer and
6944 sysschema.format_statement.
6945 Don't forget to grep for "WL#6570" in the whole tree, including mtr
6946 tests.
6947 */
6948 614819 used_tables_cache =
6949
2/2
✓ Branch 0 taken 2470 times.
✓ Branch 1 taken 612349 times.
614819 thd->lex->locate_var_assignment(name) ? RAND_TABLE_BIT : INNER_TABLE_BIT;
6950
6951 614819 mysql_mutex_lock(&thd->LOCK_thd_data);
6952 614819 var_entry = get_variable(thd, name, nullptr);
6953 614819 mysql_mutex_unlock(&thd->LOCK_thd_data);
6954
6955
2/2
✓ Branch 0 taken 600552 times.
✓ Branch 1 taken 14267 times.
614819 if (var_entry != nullptr) {
6956 // Variable exists - assign type information from the entry.
6957 600552 m_cached_result_type = var_entry->type();
6958
6959
4/5
✓ Branch 0 taken 4001 times.
✓ Branch 1 taken 270466 times.
✓ Branch 2 taken 319701 times.
✓ Branch 3 taken 6384 times.
✗ Branch 4 not taken.
600552 switch (m_cached_result_type) {
6960 4001 case REAL_RESULT:
6961 4001 set_data_type_double();
6962 4001 break;
6963 270466 case INT_RESULT:
6964 270466 set_data_type_longlong();
6965 270466 unsigned_flag = var_entry->unsigned_flag;
6966 270466 break;
6967 319701 case STRING_RESULT:
6968 319701 set_data_type_string(uint32(MAX_BLOB_WIDTH - 1), var_entry->collation);
6969 319701 break;
6970 6384 case DECIMAL_RESULT:
6971 6384 set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE);
6972 6384 break;
6973 case ROW_RESULT: // Keep compiler happy
6974 default:
6975 assert(0);
6976 break;
6977 }
6978
6979 // Override collation for all data types
6980 600552 collation.set(var_entry->collation);
6981 } else {
6982 // Unknown user variable, assign expected type from context.
6983 14267 null_value = true;
6984 }
6985 614819 collation.set(DERIVATION_IMPLICIT);
6986
6987 // Refresh the variable entry during execution with proper binlogging.
6988 614819 var_entry = nullptr;
6989
6990 614819 return false;
6991 }
6992
6993 14264 bool Item_func_get_user_var::propagate_type(THD *,
6994 const Type_properties &type) {
6995 /*
6996 If the type is temporal: user variables don't support that type; so, we
6997 use a VARCHAR instead. Same for JSON and GEOMETRY.
6998 BIT and YEAR types are represented with LONGLONG.
6999 */
7000
10/13
✓ Branch 0 taken 13787 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 430 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 16 times.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 7 times.
✗ Branch 12 not taken.
14264 switch (type.m_type) {
7001 13787 case MYSQL_TYPE_TINY:
7002 case MYSQL_TYPE_SHORT:
7003 case MYSQL_TYPE_INT24:
7004 case MYSQL_TYPE_LONG:
7005 case MYSQL_TYPE_LONGLONG:
7006 13787 set_data_type_longlong();
7007 13787 unsigned_flag = type.m_unsigned_flag;
7008 13787 break;
7009 1 case MYSQL_TYPE_BIT:
7010 1 set_data_type_longlong();
7011 1 unsigned_flag = true;
7012 1 break;
7013 case MYSQL_TYPE_YEAR:
7014 set_data_type_longlong();
7015 break;
7016 4 case MYSQL_TYPE_NEWDECIMAL:
7017 case MYSQL_TYPE_DECIMAL:
7018 4 set_data_type_decimal(DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE);
7019 4 break;
7020 12 case MYSQL_TYPE_FLOAT:
7021 case MYSQL_TYPE_DOUBLE:
7022 12 set_data_type_double();
7023 12 break;
7024 430 case MYSQL_TYPE_VARCHAR:
7025 case MYSQL_TYPE_VAR_STRING:
7026 case MYSQL_TYPE_STRING:
7027 case MYSQL_TYPE_ENUM:
7028 case MYSQL_TYPE_SET:
7029 case MYSQL_TYPE_NULL:
7030 // Parameter type is VARCHAR of largest possible size
7031 430 set_data_type_string(65535U / type.m_collation.collation->mbmaxlen,
7032 430 type.m_collation);
7033 430 break;
7034 1 case MYSQL_TYPE_GEOMETRY:
7035 1 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7036 1 break;
7037 2 case MYSQL_TYPE_JSON:
7038 2 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7039 2 break;
7040 16 case MYSQL_TYPE_TINY_BLOB:
7041 case MYSQL_TYPE_MEDIUM_BLOB:
7042 case MYSQL_TYPE_LONG_BLOB:
7043 case MYSQL_TYPE_BLOB:
7044 // Parameter type is BLOB of largest possible size
7045 16 set_data_type_string(MAX_BLOB_WIDTH, type.m_collation);
7046 16 break;
7047 4 case MYSQL_TYPE_DATETIME:
7048 case MYSQL_TYPE_DATETIME2:
7049 case MYSQL_TYPE_TIMESTAMP:
7050 case MYSQL_TYPE_TIMESTAMP2:
7051 4 set_data_type_string(26, type.m_collation);
7052 4 break;
7053 case MYSQL_TYPE_DATE:
7054 case MYSQL_TYPE_NEWDATE:
7055 set_data_type_string(10, type.m_collation);
7056 break;
7057 7 case MYSQL_TYPE_TIME:
7058 case MYSQL_TYPE_TIME2:
7059 7 set_data_type_string(15, type.m_collation);
7060 7 break;
7061 default:
7062 assert(false);
7063 }
7064 // User variables have implicit derivation
7065 14264 collation.set(DERIVATION_IMPLICIT);
7066
7067 // @todo - when result_type is refactored, this may not be necessary
7068 14264 m_cached_result_type = type_to_result(data_type());
7069
7070 14264 return false;
7071 }
7072
7073 1322817 void Item_func_get_user_var::cleanup() {
7074 1322817 Item_func::cleanup();
7075 /*
7076 Ensure that a valid user variable object is rebound on next execution. See
7077 comment in Item_func_set_user_var::cleanup().
7078 */
7079 1322825 var_entry = nullptr;
7080 1322825 }
7081
7082 3030246 enum Item_result Item_func_get_user_var::result_type() const {
7083 3030246 return m_cached_result_type;
7084 }
7085
7086 561 void Item_func_get_user_var::print(const THD *thd, String *str,
7087 enum_query_type) const {
7088 561 str->append(STRING_WITH_LEN("(@"));
7089 561 append_identifier(thd, str, name.ptr(), name.length());
7090 561 str->append(')');
7091 561 }
7092
7093 14561 bool Item_func_get_user_var::eq(const Item *item, bool) const {
7094 /* Assume we don't have rtti */
7095
2/2
✓ Branch 0 taken 7210 times.
✓ Branch 1 taken 7351 times.
14561 if (this == item) return true; // Same item is same.
7096 /* Check if other type is also a get_user_var() object */
7097
4/4
✓ Branch 0 taken 1109 times.
✓ Branch 1 taken 6242 times.
✓ Branch 2 taken 7153 times.
✓ Branch 3 taken 198 times.
8460 if (item->type() != FUNC_ITEM ||
7098
2/2
✓ Branch 0 taken 911 times.
✓ Branch 1 taken 198 times.
1109 down_cast<const Item_func *>(item)->functype() != functype())
7099 7153 return false;
7100 const Item_func_get_user_var *other =
7101 198 down_cast<const Item_func_get_user_var *>(item);
7102 198 return name.eq_bin(other->name);
7103 }
7104
7105 14333 bool Item_func_get_user_var::set_value(THD *thd, sp_rcontext * /*ctx*/,
7106 Item **it) {
7107
2/4
✓ Branch 0 taken 14333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14333 times.
✗ Branch 3 not taken.
14333 Item_func_set_user_var *suv = new Item_func_set_user_var(name, *it);
7108 /*
7109 Item_func_set_user_var is not fixed after construction, call
7110 fix_fields().
7111 */
7112
3/6
✓ Branch 0 taken 14333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14333 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14333 times.
✗ Branch 5 not taken.
28666 return (!suv || suv->fix_fields(thd, it) || suv->check(false) ||
7113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14333 times.
28666 suv->update());
7114 }
7115
7116 59 bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) {
7117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 assert(fixed == 0);
7118
7119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 assert(thd->lex->sql_command == SQLCOM_LOAD);
7120 auto exchange_cs =
7121 59 down_cast<Sql_cmd_load_table *>(thd->lex->m_sql_cmd)->m_exchange.cs;
7122 /*
7123 Let us set the same collation which is used for loading
7124 of fields in LOAD DATA INFILE.
7125 (Since Item_user_var_as_out_param is used only there).
7126 */
7127 59 const CHARSET_INFO *cs =
7128
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 2 times.
59 exchange_cs ? exchange_cs : thd->variables.collation_database;
7129
7130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (Item::fix_fields(thd, ref)) return true;
7131
7132 /* Protects thd->user_vars. */
7133 59 mysql_mutex_lock(&thd->LOCK_thd_data);
7134 59 entry = get_variable(thd, name, cs);
7135
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 if (entry != nullptr) entry->set_type(STRING_RESULT);
7136 59 mysql_mutex_unlock(&thd->LOCK_thd_data);
7137
7138 59 return entry == nullptr;
7139 }
7140
7141 24 void Item_user_var_as_out_param::set_null_value(const CHARSET_INFO *) {
7142 24 entry->lock();
7143 24 entry->set_null_value(STRING_RESULT);
7144 24 entry->unlock();
7145 24 }
7146
7147 836 void Item_user_var_as_out_param::set_value(const char *str, size_t length,
7148 const CHARSET_INFO *cs) {
7149 836 entry->lock();
7150 836 entry->store(str, length, STRING_RESULT, cs, DERIVATION_IMPLICIT,
7151 false /* unsigned_arg */);
7152 836 entry->unlock();
7153 836 }
7154
7155 double Item_user_var_as_out_param::val_real() {
7156 assert(0);
7157 return 0.0;
7158 }
7159
7160 longlong Item_user_var_as_out_param::val_int() {
7161 assert(0);
7162 return 0;
7163 }
7164
7165 String *Item_user_var_as_out_param::val_str(String *) {
7166 assert(0);
7167 return nullptr;
7168 }
7169
7170 my_decimal *Item_user_var_as_out_param::val_decimal(my_decimal *) {
7171 assert(0);
7172 return nullptr;
7173 }
7174
7175 12 void Item_user_var_as_out_param::print(const THD *thd, String *str,
7176 enum_query_type) const {
7177 12 str->append('@');
7178 12 append_identifier(thd, str, name.ptr(), name.length());
7179 12 }
7180
7181 677100 Item_func_get_system_var::Item_func_get_system_var(
7182 677100 const System_variable_tracker &var_tracker, enum_var_type scope)
7183
1/2
✓ Branch 0 taken 677099 times.
✗ Branch 1 not taken.
677100 : var_scope{scope}, cache_present{0}, var_tracker{var_tracker} {
7184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 677099 times.
677099 assert(scope != OPT_DEFAULT);
7185 677099 }
7186
7187 585907 bool Item_func_get_system_var::resolve_type(THD *) {
7188 585907 set_nullable(true);
7189
7190
5/6
✓ Branch 0 taken 183065 times.
✓ Branch 1 taken 801 times.
✓ Branch 2 taken 291323 times.
✓ Branch 3 taken 110388 times.
✓ Branch 4 taken 330 times.
✗ Branch 5 not taken.
585907 switch (var_tracker.cached_show_type()) {
7191 183065 case SHOW_LONG:
7192 case SHOW_INT:
7193 case SHOW_HA_ROWS:
7194 case SHOW_LONGLONG:
7195 183065 set_data_type_longlong();
7196 183065 unsigned_flag = true;
7197 183065 break;
7198 801 case SHOW_SIGNED_INT:
7199 case SHOW_SIGNED_LONG:
7200 case SHOW_SIGNED_LONGLONG:
7201 801 set_data_type_longlong();
7202 801 unsigned_flag = false;
7203 801 break;
7204 291323 case SHOW_CHAR:
7205 case SHOW_CHAR_PTR:
7206 case SHOW_LEX_STRING:
7207 291323 collation.set(system_charset_info, DERIVATION_SYSCONST);
7208 291323 set_data_type_string(65535U / collation.collation->mbmaxlen);
7209 291323 break;
7210 110388 case SHOW_BOOL:
7211 case SHOW_MY_BOOL:
7212 110388 set_data_type_longlong();
7213 110388 max_length = 1;
7214 110388 break;
7215 330 case SHOW_DOUBLE:
7216 330 set_data_type_double();
7217 // Override decimals and length calculation done above.
7218 330 decimals = 6;
7219 330 max_length = float_length(decimals);
7220 330 break;
7221 default:
7222 my_error(ER_VAR_CANT_BE_READ, MYF(0), var_tracker.get_var_name());
7223 return true;
7224 }
7225 585907 return false;
7226 }
7227
7228 36 void Item_func_get_system_var::print(const THD *, String *str,
7229 enum_query_type) const {
7230 36 str->append(item_name);
7231 36 }
7232
7233 661490 Audit_global_variable_get_event::Audit_global_variable_get_event(
7234 661490 THD *thd, Item_func_get_system_var *item, uchar cache_type)
7235 661490 : m_thd(thd), m_item(item), m_val_type(cache_type) {
7236 // Variable is of GLOBAL scope.
7237 661490 bool is_global_var = m_item->var_scope == OPT_GLOBAL;
7238
7239 // Event is already audited for the same query.
7240 661490 bool event_is_audited =
7241
3/4
✓ Branch 0 taken 774 times.
✓ Branch 1 taken 660716 times.
✓ Branch 2 taken 774 times.
✗ Branch 3 not taken.
661490 m_item->cache_present != 0 && m_item->used_query_id == m_thd->query_id;
7242
7243
4/4
✓ Branch 0 taken 540356 times.
✓ Branch 1 taken 121134 times.
✓ Branch 2 taken 539655 times.
✓ Branch 3 taken 701 times.
661490 m_audit_event = (is_global_var && !event_is_audited);
7244 661490 }
7245
7246 661502 Audit_global_variable_get_event::~Audit_global_variable_get_event() {
7247 /*
7248 While converting value to string, integer or real type, if the value is
7249 cached for the types other then m_val_type for intermediate type
7250 conversions then event is already notified.
7251 */
7252 661502 bool event_already_notified = (m_item->cache_present & (~m_val_type));
7253
7254
4/4
✓ Branch 0 taken 539657 times.
✓ Branch 1 taken 121845 times.
✓ Branch 2 taken 506966 times.
✓ Branch 3 taken 32691 times.
661502 if (m_audit_event && !event_already_notified) {
7255 506966 String str;
7256 506966 String *outStr = nullptr;
7257
7258
4/6
✓ Branch 0 taken 374 times.
✓ Branch 1 taken 506592 times.
✓ Branch 2 taken 374 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 506966 times.
✗ Branch 5 not taken.
506966 if (!m_item->cached_null_value || !m_thd->is_error()) {
7259 506966 outStr = &str;
7260
7261
2/4
✓ Branch 0 taken 506966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 506966 times.
✗ Branch 3 not taken.
506966 assert(m_item->cache_present != 0 &&
7262 m_item->used_query_id == m_thd->query_id);
7263
7264
2/2
✓ Branch 0 taken 301385 times.
✓ Branch 1 taken 205581 times.
506966 if (m_item->cache_present & GET_SYS_VAR_CACHE_STRING)
7265 301385 outStr = &m_item->cached_strval;
7266
2/2
✓ Branch 0 taken 205429 times.
✓ Branch 1 taken 152 times.
205581 else if (m_item->cache_present & GET_SYS_VAR_CACHE_LONG)
7267 205429 str.set(m_item->cached_llval, m_item->collation.collation);
7268
1/2
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
152 else if (m_item->cache_present & GET_SYS_VAR_CACHE_DOUBLE)
7269 152 str.set_real(m_item->cached_dval, m_item->decimals,
7270 152 m_item->collation.collation);
7271 }
7272
7273
2/4
✓ Branch 0 taken 506966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 506966 times.
✗ Branch 3 not taken.
1520898 mysql_audit_notify(m_thd, AUDIT_EVENT(MYSQL_AUDIT_GLOBAL_VARIABLE_GET),
7274 506966 m_item->var_tracker.get_var_name(),
7275 506966 outStr ? outStr->ptr() : nullptr,
7276 506966 outStr ? outStr->length() : 0);
7277 506966 }
7278 661502 }
7279
7280 template <typename T>
7281 593950 longlong Item_func_get_system_var::get_sys_var_safe(THD *thd, sys_var *var) {
7282 593950 T value = {};
7283 {
7284 593950 MUTEX_LOCK(lock, &LOCK_global_system_variables);
7285 593950 std::string_view keycache_name = var_tracker.get_keycache_name();
7286 593950 value =
7287
1/2
✓ Branch 0 taken 296975 times.
✗ Branch 1 not taken.
593950 *pointer_cast<const T *>(var->value_ptr(thd, var_scope, keycache_name));
7288 593950 }
7289 593950 cache_present |= GET_SYS_VAR_CACHE_LONG;
7290 593950 used_query_id = thd->query_id;
7291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 296975 times.
593950 cached_llval = null_value ? 0LL : static_cast<longlong>(value);
7292 593950 cached_null_value = null_value;
7293 593950 return cached_llval;
7294 }
7295
7296 297476 longlong Item_func_get_system_var::val_int() {
7297
1/2
✓ Branch 0 taken 297477 times.
✗ Branch 1 not taken.
297476 THD *thd = current_thd;
7298 Audit_global_variable_get_event audit_sys_var(thd, this,
7299
1/2
✓ Branch 0 taken 297478 times.
✗ Branch 1 not taken.
297477 GET_SYS_VAR_CACHE_LONG);
7300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 297478 times.
297478 assert(fixed);
7301
7302
3/4
✓ Branch 0 taken 501 times.
✓ Branch 1 taken 296977 times.
✓ Branch 2 taken 501 times.
✗ Branch 3 not taken.
297478 if (cache_present && thd->query_id == used_query_id) {
7303
1/2
✓ Branch 0 taken 501 times.
✗ Branch 1 not taken.
501 if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7304 501 null_value = cached_null_value;
7305 501 return cached_llval;
7306 } else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7307 null_value = cached_null_value;
7308 cached_llval = (longlong)cached_dval;
7309 cache_present |= GET_SYS_VAR_CACHE_LONG;
7310 return cached_llval;
7311 } else if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7312 null_value = cached_null_value;
7313 if (!null_value)
7314 cached_llval = longlong_from_string_with_check(
7315 cached_strval.charset(), cached_strval.c_ptr(),
7316 cached_strval.c_ptr() + cached_strval.length(), unsigned_flag);
7317 else
7318 cached_llval = 0;
7319 cache_present |= GET_SYS_VAR_CACHE_LONG;
7320 return cached_llval;
7321 }
7322 }
7323
7324 296977 auto f = [this, thd](const System_variable_tracker &,
7325 296982 sys_var *var) -> longlong {
7326
9/12
✓ Branch 0 taken 20010 times.
✓ Branch 1 taken 156546 times.
✓ Branch 2 taken 8850 times.
✓ Branch 3 taken 347 times.
✓ Branch 4 taken 271 times.
✓ Branch 5 taken 195 times.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 110692 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
296977 switch (var->show_type()) {
7327 20010 case SHOW_INT:
7328 20010 return get_sys_var_safe<uint>(thd, var);
7329 156546 case SHOW_LONG:
7330 156546 return get_sys_var_safe<ulong>(thd, var);
7331 8850 case SHOW_LONGLONG:
7332 8850 return get_sys_var_safe<ulonglong>(thd, var);
7333 347 case SHOW_SIGNED_INT:
7334 347 return get_sys_var_safe<int>(thd, var);
7335 271 case SHOW_SIGNED_LONG:
7336 271 return get_sys_var_safe<long>(thd, var);
7337 195 case SHOW_SIGNED_LONGLONG:
7338 195 return get_sys_var_safe<longlong>(thd, var);
7339 64 case SHOW_HA_ROWS:
7340 64 return get_sys_var_safe<ha_rows>(thd, var);
7341 case SHOW_BOOL:
7342 return get_sys_var_safe<bool>(thd, var);
7343 110692 case SHOW_MY_BOOL:
7344 110692 return get_sys_var_safe<bool>(thd, var);
7345 case SHOW_DOUBLE: {
7346 double dval = val_real();
7347
7348 used_query_id = thd->query_id;
7349 cached_llval = (longlong)dval;
7350 cache_present |= GET_SYS_VAR_CACHE_LONG;
7351 return cached_llval;
7352 }
7353 2 case SHOW_CHAR:
7354 case SHOW_CHAR_PTR:
7355 case SHOW_LEX_STRING: {
7356 2 String *str_val = val_str(nullptr);
7357 // Treat empty strings as NULL, like val_real() does.
7358
5/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
2 if (str_val && str_val->length())
7359 1 cached_llval = longlong_from_string_with_check(
7360 1 system_charset_info, str_val->c_ptr(),
7361 1 str_val->c_ptr() + str_val->length(), unsigned_flag);
7362 else {
7363 1 null_value = true;
7364 1 cached_llval = 0;
7365 }
7366
7367 2 cache_present |= GET_SYS_VAR_CACHE_LONG;
7368 2 return cached_llval;
7369 }
7370
7371 default:
7372 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7373 return 0; // keep the compiler happy
7374 }
7375 296977 };
7376
1/2
✓ Branch 0 taken 296977 times.
✗ Branch 1 not taken.
296977 return var_tracker.access_system_variable<longlong>(thd, f).value_or(0);
7377 297478 }
7378
7379 360681 String *Item_func_get_system_var::val_str(String *str) {
7380
4/6
✓ Branch 0 taken 359870 times.
✓ Branch 1 taken 817 times.
✓ Branch 2 taken 359871 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 359872 times.
✗ Branch 5 not taken.
360681 DEBUG_SYNC(current_thd, "after_error_checking");
7381
1/2
✓ Branch 0 taken 360690 times.
✗ Branch 1 not taken.
360689 THD *thd = current_thd;
7382 Audit_global_variable_get_event audit_sys_var(thd, this,
7383
1/2
✓ Branch 0 taken 360691 times.
✗ Branch 1 not taken.
360690 GET_SYS_VAR_CACHE_STRING);
7384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360691 times.
360691 assert(fixed);
7385
7386
3/4
✓ Branch 0 taken 267 times.
✓ Branch 1 taken 360424 times.
✓ Branch 2 taken 267 times.
✗ Branch 3 not taken.
360691 if (cache_present && thd->query_id == used_query_id) {
7387
2/2
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 7 times.
267 if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7388 260 null_value = cached_null_value;
7389
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 256 times.
260 return null_value ? nullptr : &cached_strval;
7390
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 } else if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7391 7 null_value = cached_null_value;
7392
2/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 if (!null_value) cached_strval.set(cached_llval, collation.collation);
7393 7 cache_present |= GET_SYS_VAR_CACHE_STRING;
7394
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 return null_value ? nullptr : &cached_strval;
7395 } else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7396 null_value = cached_null_value;
7397 if (!null_value)
7398 cached_strval.set_real(cached_dval, decimals, collation.collation);
7399 cache_present |= GET_SYS_VAR_CACHE_STRING;
7400 return null_value ? nullptr : &cached_strval;
7401 }
7402 }
7403
7404 360424 str = &cached_strval;
7405 360424 null_value = false;
7406
7407 1412180 auto f = [this, thd, &str](const System_variable_tracker &, sys_var *var) {
7408
2/4
✓ Branch 0 taken 330655 times.
✓ Branch 1 taken 29763 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
360414 switch (var->show_type()) {
7409 330655 case SHOW_CHAR:
7410 case SHOW_CHAR_PTR:
7411 case SHOW_LEX_STRING: {
7412 330655 mysql_mutex_lock(&LOCK_global_system_variables);
7413 const char *cptr =
7414 330662 var->show_type() == SHOW_CHAR
7415
2/2
✓ Branch 0 taken 159614 times.
✓ Branch 1 taken 171048 times.
661324 ? pointer_cast<const char *>(var->value_ptr(
7416 159614 thd, var_scope, var_tracker.get_keycache_name()))
7417 342096 : *pointer_cast<const char *const *>(var->value_ptr(
7418 171048 thd, var_scope, var_tracker.get_keycache_name()));
7419
2/2
✓ Branch 0 taken 330219 times.
✓ Branch 1 taken 443 times.
330662 if (cptr) {
7420 size_t len =
7421 330219 var->show_type() == SHOW_LEX_STRING
7422
2/2
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 330092 times.
330346 ? (pointer_cast<const LEX_STRING *>(var->value_ptr(
7423 127 thd, var_scope, var_tracker.get_keycache_name())))
7424 ->length
7425 330092 : strlen(cptr);
7426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330219 times.
330219 if (str->copy(cptr, len, collation.collation)) {
7427 null_value = true;
7428 str = nullptr;
7429 }
7430 } else {
7431 443 null_value = true;
7432 443 str = nullptr;
7433 }
7434 330662 mysql_mutex_unlock(&LOCK_global_system_variables);
7435 330662 break;
7436 }
7437
7438 29763 case SHOW_INT:
7439 case SHOW_LONG:
7440 case SHOW_LONGLONG:
7441 case SHOW_SIGNED_INT:
7442 case SHOW_SIGNED_LONG:
7443 case SHOW_SIGNED_LONGLONG:
7444 case SHOW_HA_ROWS:
7445 case SHOW_BOOL:
7446 case SHOW_MY_BOOL:
7447
2/2
✓ Branch 0 taken 29762 times.
✓ Branch 1 taken 1 times.
29763 if (unsigned_flag)
7448 29762 str->set((ulonglong)val_int(), collation.collation);
7449 else
7450 1 str->set(val_int(), collation.collation);
7451 29763 break;
7452 case SHOW_DOUBLE:
7453 str->set_real(val_real(), decimals, collation.collation);
7454 break;
7455
7456 default:
7457 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7458 str = error_str();
7459 break;
7460 }
7461 720849 };
7462
3/6
✓ Branch 0 taken 360418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 360425 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 360425 times.
360424 if (var_tracker.access_system_variable(thd, f)) {
7463 str = error_str();
7464 }
7465
7466 360425 cache_present |= GET_SYS_VAR_CACHE_STRING;
7467 360425 used_query_id = thd->query_id;
7468 360425 cached_null_value = null_value;
7469 360425 return str;
7470 360692 }
7471
7472 3332 double Item_func_get_system_var::val_real() {
7473
1/2
✓ Branch 0 taken 3332 times.
✗ Branch 1 not taken.
3332 THD *thd = current_thd;
7474 Audit_global_variable_get_event audit_sys_var(thd, this,
7475
1/2
✓ Branch 0 taken 3332 times.
✗ Branch 1 not taken.
3332 GET_SYS_VAR_CACHE_DOUBLE);
7476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3332 times.
3332 assert(fixed);
7477
7478
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3326 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
3332 if (cache_present && thd->query_id == used_query_id) {
7479
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (cache_present & GET_SYS_VAR_CACHE_DOUBLE) {
7480 6 null_value = cached_null_value;
7481 6 return cached_dval;
7482 } else if (cache_present & GET_SYS_VAR_CACHE_LONG) {
7483 null_value = cached_null_value;
7484 cached_dval = (double)cached_llval;
7485 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7486 return cached_dval;
7487 } else if (cache_present & GET_SYS_VAR_CACHE_STRING) {
7488 null_value = cached_null_value;
7489 if (!null_value)
7490 cached_dval = double_from_string_with_check(
7491 cached_strval.charset(), cached_strval.c_ptr(),
7492 cached_strval.c_ptr() + cached_strval.length());
7493 else
7494 cached_dval = 0;
7495 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7496 return cached_dval;
7497 }
7498 }
7499
7500 3326 auto f = [this, thd](const System_variable_tracker &,
7501 7656 sys_var *var) -> double {
7502
3/4
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2989 times.
✗ Branch 3 not taken.
3326 switch (var->show_type()) {
7503 330 case SHOW_DOUBLE:
7504 330 mysql_mutex_lock(&LOCK_global_system_variables);
7505 990 cached_dval = *pointer_cast<const double *>(
7506 330 var->value_ptr(thd, var_scope, var_tracker.get_keycache_name()));
7507 330 mysql_mutex_unlock(&LOCK_global_system_variables);
7508 330 used_query_id = thd->query_id;
7509 330 cached_null_value = null_value;
7510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 330 times.
330 if (null_value) cached_dval = 0;
7511 330 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7512 330 return cached_dval;
7513 7 case SHOW_CHAR:
7514 case SHOW_LEX_STRING:
7515 case SHOW_CHAR_PTR: {
7516 7 mysql_mutex_lock(&LOCK_global_system_variables);
7517 const char *cptr =
7518 7 var->show_type() == SHOW_CHAR
7519
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
14 ? pointer_cast<const char *>(var->value_ptr(
7520 7 thd, var_scope, var_tracker.get_keycache_name()))
7521 : *pointer_cast<const char *const *>(var->value_ptr(
7522 thd, var_scope, var_tracker.get_keycache_name()));
7523 // Treat empty strings as NULL, like val_int() does.
7524
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
7 if (cptr && *cptr)
7525 6 cached_dval = double_from_string_with_check(system_charset_info, cptr,
7526 6 cptr + strlen(cptr));
7527 else {
7528 1 null_value = true;
7529 1 cached_dval = 0;
7530 }
7531 7 mysql_mutex_unlock(&LOCK_global_system_variables);
7532 7 used_query_id = thd->query_id;
7533 7 cached_null_value = null_value;
7534 7 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7535 7 return cached_dval;
7536 }
7537 2989 case SHOW_INT:
7538 case SHOW_LONG:
7539 case SHOW_LONGLONG:
7540 case SHOW_SIGNED_INT:
7541 case SHOW_SIGNED_LONG:
7542 case SHOW_SIGNED_LONGLONG:
7543 case SHOW_HA_ROWS:
7544 case SHOW_BOOL:
7545 case SHOW_MY_BOOL:
7546 2989 cached_dval = (double)val_int();
7547 2989 cache_present |= GET_SYS_VAR_CACHE_DOUBLE;
7548 2989 used_query_id = thd->query_id;
7549 2989 cached_null_value = null_value;
7550 2989 return cached_dval;
7551 default:
7552 my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
7553 return 0;
7554 }
7555 3326 };
7556
1/2
✓ Branch 0 taken 3326 times.
✗ Branch 1 not taken.
3326 return var_tracker.access_system_variable<double>(thd, f).value_or(0);
7557 3332 }
7558
7559 bool Item_func_get_system_var::eq(const Item *item, bool) const {
7560 /* Assume we don't have rtti */
7561 if (this == item) return true; // Same item is same.
7562 /* Check if other type is also a get_user_var() object */
7563 if (item->type() != FUNC_ITEM ||
7564 down_cast<const Item_func *>(item)->functype() != functype())
7565 return false;
7566 const Item_func_get_system_var *other =
7567 down_cast<const Item_func_get_system_var *>(item);
7568 return var_tracker == other->var_tracker;
7569 }
7570
7571 629470 void Item_func_get_system_var::cleanup() {
7572 629470 Item_func::cleanup();
7573 629470 cache_present = 0;
7574 629470 cached_strval.mem_free();
7575 629470 }
7576
7577 2796 bool Item_func_match::itemize(Parse_context *pc, Item **res) {
7578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2796 times.
2796 if (skip_itemize(res)) return false;
7579
5/6
✓ Branch 0 taken 2792 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2792 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 2792 times.
2796 if (super::itemize(pc, res) || against->itemize(pc, &against)) return true;
7580 2792 add_accum_properties(against);
7581
7582 2792 pc->select->add_ftfunc_to_list(this);
7583 2792 pc->thd->lex->set_using_match();
7584
7585
2/2
✓ Branch 0 taken 2523 times.
✓ Branch 1 taken 269 times.
2792 switch (pc->select->parsing_place) {
7586 2523 case CTX_WHERE:
7587 case CTX_ON:
7588 2523 used_in_where_only = true;
7589 2523 break;
7590 269 default:
7591 269 used_in_where_only = false;
7592 }
7593
7594 2792 return false;
7595 }
7596
7597 /**
7598 Initialize searching within full-text index.
7599
7600 @param thd Thread handler
7601
7602 @returns false if success, true if error
7603 */
7604
7605 2776 bool Item_func_match::init_search(THD *thd) {
7606
1/2
✓ Branch 0 taken 2776 times.
✗ Branch 1 not taken.
2776 DBUG_TRACE;
7607
7608 /*
7609 We will skip execution if the item is not fixed
7610 with fix_field
7611 */
7612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2776 times.
2776 if (!fixed) return false;
7613
7614 2776 TABLE *const table = table_ref->table;
7615 /* Check if init_search() has been called before */
7616
3/4
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 2663 times.
✓ Branch 2 taken 113 times.
✗ Branch 3 not taken.
2776 if (ft_handler && !master) {
7617 // Update handler::ft_handler even if the search is already initialized.
7618 // If the first call to init_search() was done before we had decided if
7619 // an index scan should be used, and we later decide that we will use
7620 // one, ft_handler is not set. For example, the optimizer calls
7621 // init_search() early if it needs to call Item_func_match::get_count()
7622 // to perform COUNT(*) optimization or decide if a LIMIT clause can be
7623 // satisfied by an index scan.
7624
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 15 times.
113 if (score_from_index_scan) table->file->ft_handler = ft_handler;
7625 113 return false;
7626 }
7627
7628
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2637 times.
2663 if (key == NO_SUCH_KEY) {
7629 26 mem_root_deque<Item *> fields(thd->mem_root);
7630
3/6
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 fields.push_back(new Item_string(" ", 1, cmp_collation.collation));
7631
3/4
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 26 times.
59 for (uint i = 0; i < arg_count; i++) fields.push_back(args[i]);
7632
2/4
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
26 concat_ws = new Item_func_concat_ws(&fields);
7633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (concat_ws == nullptr) return true;
7634 /*
7635 Above function used only to get value and do not need fix_fields for it:
7636 Item_string - basic constant
7637 fields - fix_fields() was already called for this arguments
7638 Item_func_concat_ws - do not need fix_fields() to produce value
7639 */
7640 26 concat_ws->quick_fix_field();
7641
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 }
7642
7643
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 2569 times.
2663 if (master) {
7644
2/4
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 94 times.
94 if (master->init_search(thd)) return true;
7645
7646 94 ft_handler = master->ft_handler;
7647 94 return false;
7648 }
7649
7650 2569 String *ft_tmp = nullptr;
7651
7652 // MATCH ... AGAINST (NULL) is meaningless, but possible
7653
3/4
✓ Branch 0 taken 2569 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2566 times.
2569 if (!(ft_tmp = key_item()->val_str(&value))) {
7654 3 ft_tmp = &value;
7655
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 value.set("", 0, cmp_collation.collation);
7656 }
7657
7658
2/2
✓ Branch 0 taken 1290 times.
✓ Branch 1 taken 1279 times.
2569 if (ft_tmp->charset() != cmp_collation.collation) {
7659 uint dummy_errors;
7660
1/2
✓ Branch 0 taken 1290 times.
✗ Branch 1 not taken.
1290 search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
7661 cmp_collation.collation, &dummy_errors);
7662 1290 ft_tmp = &search_value;
7663 }
7664
7665
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
2569 if (!table->is_created()) {
7666 my_error(ER_NO_FT_MATERIALIZED_SUBQUERY, MYF(0));
7667 return true;
7668 }
7669
7670
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569 times.
2569 assert(master == nullptr);
7671
1/2
✓ Branch 0 taken 2569 times.
✗ Branch 1 not taken.
2569 ft_handler = table->file->ft_init_ext_with_hints(key, ft_tmp, get_hints());
7672
7/8
✓ Branch 0 taken 2562 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2562 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2560 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 2560 times.
2569 if (ft_handler == nullptr || thd->is_error()) {
7673 9 return true;
7674 }
7675
7676
2/2
✓ Branch 0 taken 2133 times.
✓ Branch 1 taken 427 times.
2560 if (score_from_index_scan) table->file->ft_handler = ft_handler;
7677
7678 2560 return false;
7679 2776 }
7680
7681 339 float Item_func_match::get_filtering_effect(THD *, table_map filter_for_table,
7682 table_map read_tables,
7683 const MY_BITMAP *fields_to_ignore,
7684 double rows_in_table) {
7685 const Item_field *fld =
7686 339 contributes_to_filter(read_tables, filter_for_table, fields_to_ignore);
7687
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 167 times.
339 if (!fld) return COND_FILTER_ALLPASS;
7688
7689 /*
7690 MATCH () ... AGAINST" is similar to "LIKE '...'" which has the
7691 same selectivity as "col BETWEEN ...".
7692 */
7693 167 return fld->get_cond_filter_default_probability(rows_in_table,
7694 167 COND_FILTER_BETWEEN);
7695 }
7696
7697 /**
7698 Add field into table read set.
7699
7700 @param field field to be added to the table read set.
7701 */
7702 3789 static void update_table_read_set(const Field *field) {
7703 3789 TABLE *table = field->table;
7704
7705
2/2
✓ Branch 0 taken 594 times.
✓ Branch 1 taken 3195 times.
3789 if (!bitmap_test_and_set(table->read_set, field->field_index()))
7706 594 table->covering_keys.intersect(field->part_of_key);
7707 3789 }
7708
7709 2776 bool Item_func_match::fix_fields(THD *thd, Item **ref) {
7710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2776 times.
2776 assert(fixed == 0);
7711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2776 times.
2776 assert(arg_count > 0);
7712 2776 Item *item = nullptr; // Safe as arg_count is > 1
7713
7714 2776 set_nullable(true);
7715
7716 /*
7717 const_item is assumed in quite a bit of places, so it would be difficult
7718 to remove; If it would ever to be removed, this should include
7719 modifications to find_best and auto_close as complement to auto_init code
7720 above.
7721 */
7722 2776 enum_mark_columns save_mark_used_columns = thd->mark_used_columns;
7723 /*
7724 Since different engines require different columns for FTS index lookup
7725 we prevent updating of table read_set in argument's ::fix_fields().
7726 */
7727 2776 thd->mark_used_columns = MARK_COLUMNS_NONE;
7728
4/6
✓ Branch 0 taken 2776 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2776 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2774 times.
5552 if (Item_func::fix_fields(thd, ref) || fix_func_arg(thd, &against) ||
7729
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2774 times.
2776 !against->const_for_execution()) {
7730 2 thd->mark_used_columns = save_mark_used_columns;
7731 2 my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
7732 2 return true;
7733 }
7734 2774 thd->mark_used_columns = save_mark_used_columns;
7735
7736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2774 times.
2774 if (against->propagate_type(thd)) return true;
7737
7738 2774 bool allows_multi_table_search = true;
7739
2/2
✓ Branch 0 taken 4103 times.
✓ Branch 1 taken 2767 times.
6870 for (uint i = 0; i < arg_count; i++) {
7740 4103 item = args[i] = args[i]->real_item();
7741
4/4
✓ Branch 0 taken 4101 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4096 times.
8204 if (item->type() != Item::FIELD_ITEM ||
7742 /* Cannot use FTS index with outer table field */
7743
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4096 times.
4101 item->is_outer_reference()) {
7744 7 my_error(ER_WRONG_ARGUMENTS, MYF(0), "MATCH");
7745 7 return true;
7746 }
7747 4096 allows_multi_table_search &= allows_search_on_non_indexed_columns(
7748 4096 ((Item_field *)item)->field->table);
7749 }
7750
7751 /*
7752 Check that all columns come from the same table.
7753 We've already checked that columns in MATCH are fields so
7754 INNER_TABLE_BIT can only appear from AGAINST argument.
7755 */
7756
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2759 times.
2767 if ((used_tables_cache & ~INNER_TABLE_BIT) != item->used_tables())
7757 8 key = NO_SUCH_KEY;
7758
7759
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2759 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
2767 if (key == NO_SUCH_KEY && !allows_multi_table_search) {
7760 5 my_error(ER_WRONG_ARGUMENTS, MYF(0), "MATCH");
7761 5 return true;
7762 }
7763 2762 table_ref = ((Item_field *)item)->table_ref;
7764
7765
1/2
✓ Branch 0 taken 2762 times.
✗ Branch 1 not taken.
2762 if (table_ref != nullptr) table_ref->set_fulltext_searched();
7766
7767 /*
7768 Here we make an assumption that if the engine supports
7769 fulltext extension(HA_CAN_FULLTEXT_EXT flag) then table
7770 can have FTS_DOC_ID column. Atm this is the only way
7771 to distinguish MyISAM and InnoDB engines.
7772 Generally table_ref should be available, but in case of
7773 a generated column's generation expression it's not. Thus
7774 we use field's table, at this moment it's already available.
7775 */
7776 2762 TABLE *const table =
7777
1/2
✓ Branch 0 taken 2762 times.
✗ Branch 1 not taken.
2762 table_ref ? table_ref->table : ((Item_field *)item)->field->table;
7778
7779
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 2749 times.
2762 if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT)) {
7780 13 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
7781 13 return true;
7782 }
7783
7784
2/2
✓ Branch 0 taken 2363 times.
✓ Branch 1 taken 386 times.
2749 if ((table->file->ha_table_flags() & HA_CAN_FULLTEXT_EXT)) {
7785 2363 Field *doc_id_field = table->fts_doc_id_field;
7786 /*
7787 Update read set with FTS_DOC_ID column so that indexes that have
7788 FTS_DOC_ID part can be considered as a covering index.
7789 */
7790
2/2
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 2020 times.
2363 if (doc_id_field)
7791 343 update_table_read_set(doc_id_field);
7792 else {
7793 /* read_set needs to be updated for MATCH arguments */
7794
2/2
✓ Branch 0 taken 2969 times.
✓ Branch 1 taken 2020 times.
4989 for (uint i = 0; i < arg_count; i++)
7795 2969 update_table_read_set(((Item_field *)args[i])->field);
7796 /*
7797 Prevent index only access by non-FTS index if table does not have
7798 FTS_DOC_ID column, find_relevance does not work properly without
7799 FTS_DOC_ID value. Decision for FTS index about index only access
7800 is made later by JOIN::fts_index_access() function.
7801 */
7802 2020 table->covering_keys.clear_all();
7803 }
7804
7805 } else {
7806 /*
7807 Since read_set is not updated for MATCH arguments
7808 it's necessary to update it here for MyISAM.
7809 */
7810
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 386 times.
863 for (uint i = 0; i < arg_count; i++)
7811 477 update_table_read_set(((Item_field *)args[i])->field);
7812 }
7813
7814
1/2
✓ Branch 0 taken 2749 times.
✗ Branch 1 not taken.
2749 if (!master) {
7815
1/2
✓ Branch 0 taken 2749 times.
✗ Branch 1 not taken.
2749 Prepared_stmt_arena_holder ps_arena_holder(thd);
7816
1/2
✓ Branch 0 taken 2749 times.
✗ Branch 1 not taken.
2749 hints = new (thd->mem_root) Ft_hints(flags);
7817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2749 times.
2749 if (!hints) {
7818 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
7819 return true;
7820 }
7821
1/2
✓ Branch 0 taken 2749 times.
✗ Branch 1 not taken.
2749 }
7822 2749 return agg_item_collations_for_comparison(cmp_collation, func_name(), args,
7823 2749 arg_count, 0);
7824 }
7825
7826 2739 bool Item_func_match::fix_index(const THD *thd) {
7827 TABLE *table;
7828 2739 uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts = 0, keynr;
7829 2739 uint max_cnt = 0, mkeys = 0, i;
7830
7831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2739 times.
2739 if (!table_ref) goto err;
7832
7833 /*
7834 We will skip execution if the item is not fixed
7835 with fix_field
7836 */
7837
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2739 times.
2739 if (!fixed) {
7838 if (allows_search_on_non_indexed_columns(table_ref->table))
7839 key = NO_SUCH_KEY;
7840
7841 return false;
7842 }
7843
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2736 times.
2739 if (key == NO_SUCH_KEY) return false;
7844
7845 2736 table = table_ref->table;
7846
2/2
✓ Branch 0 taken 10168 times.
✓ Branch 1 taken 2736 times.
12904 for (keynr = 0; keynr < table->s->keys; keynr++) {
7847
2/2
✓ Branch 0 taken 8090 times.
✓ Branch 1 taken 2078 times.
18258 if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
7848
4/4
✓ Branch 0 taken 4525 times.
✓ Branch 1 taken 3565 times.
✓ Branch 2 taken 4515 times.
✓ Branch 3 taken 10 times.
8090 (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr)
7849
5/6
✓ Branch 0 taken 3565 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3562 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 8077 times.
✓ Branch 5 taken 2091 times.
13733 : table->s->usable_indexes(thd).is_set(keynr)))
7850
7851 {
7852 8077 ft_to_key[fts] = keynr;
7853 8077 ft_cnt[fts] = 0;
7854 8077 fts++;
7855 }
7856 }
7857
7858
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2695 times.
2736 if (!fts) goto err;
7859
7860
2/2
✓ Branch 0 taken 4004 times.
✓ Branch 1 taken 2695 times.
6699 for (i = 0; i < arg_count; i++) {
7861 Item_field *item =
7862
2/4
✓ Branch 0 taken 4004 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4004 times.
✗ Branch 3 not taken.
4004 down_cast<Item_field *>(unwrap_rollup_group(args[i])->real_item());
7863
2/2
✓ Branch 0 taken 10883 times.
✓ Branch 1 taken 4004 times.
14887 for (keynr = 0; keynr < fts; keynr++) {
7864 10883 KEY *ft_key = &table->key_info[ft_to_key[keynr]];
7865 10883 uint key_parts = ft_key->user_defined_key_parts;
7866
7867
2/2
✓ Branch 0 taken 14726 times.
✓ Branch 1 taken 10883 times.
25609 for (uint part = 0; part < key_parts; part++) {
7868
3/4
✓ Branch 0 taken 14726 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4769 times.
✓ Branch 3 taken 9957 times.
14726 if (item->field->eq(ft_key->key_part[part].field)) ft_cnt[keynr]++;
7869 }
7870 }
7871 }
7872
7873
2/2
✓ Branch 0 taken 8077 times.
✓ Branch 1 taken 2695 times.
10772 for (keynr = 0; keynr < fts; keynr++) {
7874
2/2
✓ Branch 0 taken 2818 times.
✓ Branch 1 taken 5259 times.
8077 if (ft_cnt[keynr] > max_cnt) {
7875 2818 mkeys = 0;
7876 2818 max_cnt = ft_cnt[mkeys] = ft_cnt[keynr];
7877 2818 ft_to_key[mkeys] = ft_to_key[keynr];
7878 2818 continue;
7879 }
7880
4/4
✓ Branch 0 taken 3068 times.
✓ Branch 1 taken 2191 times.
✓ Branch 2 taken 400 times.
✓ Branch 3 taken 2668 times.
5259 if (max_cnt && ft_cnt[keynr] == max_cnt) {
7881 400 mkeys++;
7882 400 ft_cnt[mkeys] = ft_cnt[keynr];
7883 400 ft_to_key[mkeys] = ft_to_key[keynr];
7884 400 continue;
7885 }
7886 }
7887
7888
2/2
✓ Branch 0 taken 2751 times.
✓ Branch 1 taken 12 times.
2763 for (keynr = 0; keynr <= mkeys; keynr++) {
7889 // partial keys doesn't work
7890
2/2
✓ Branch 0 taken 2741 times.
✓ Branch 1 taken 10 times.
2751 if (max_cnt < arg_count ||
7891
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2683 times.
2741 max_cnt < table->key_info[ft_to_key[keynr]].user_defined_key_parts)
7892 68 continue;
7893
7894 2683 key = ft_to_key[keynr];
7895
7896 2683 return false;
7897 }
7898
7899 12 err:
7900
5/6
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 30 times.
106 if (table_ref != nullptr &&
7901 53 allows_search_on_non_indexed_columns(table_ref->table)) {
7902 23 key = NO_SUCH_KEY;
7903 23 return false;
7904 }
7905
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 my_error(ER_FT_MATCHING_KEY_NOT_FOUND, MYF(0));
7906 30 return true;
7907 }
7908
7909 696 bool Item_func_match::eq(const Item *item, bool binary_cmp) const {
7910 /* We ignore FT_SORTED flag when checking for equality since result is
7911 equivalent regardless of sorting */
7912
4/4
✓ Branch 0 taken 357 times.
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 366 times.
✓ Branch 3 taken 330 times.
1053 if (!is_function_of_type(item, FT_FUNC) ||
7913 357 (flags | FT_SORTED) !=
7914
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 330 times.
357 (down_cast<const Item_func_match *>(item)->flags | FT_SORTED))
7915 366 return false;
7916
7917 330 const Item_func_match *ifm = down_cast<const Item_func_match *>(item);
7918
7919
6/6
✓ Branch 0 taken 327 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 304 times.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 248 times.
✓ Branch 5 taken 82 times.
634 if (key == ifm->key && table_ref == ifm->table_ref &&
7920
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 56 times.
304 key_item()->eq(ifm->key_item(), binary_cmp))
7921 248 return true;
7922
7923 82 return false;
7924 }
7925
7926 28605 double Item_func_match::val_real() {
7927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28605 times.
28605 assert(fixed);
7928
7929 // MATCH only knows how to get the score for base columns. Other types of
7930 // expressions (such as function calls or rollup columns) should have been
7931 // rejected during resolving.
7932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28605 times.
28605 assert(!has_rollup_expr());
7933
2/4
✓ Branch 0 taken 28605 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28605 times.
61311 assert(std::all_of(args, args + arg_count, [](const Item *item) {
7934 return item->real_item()->type() == FIELD_ITEM;
7935 }));
7936
7937
1/2
✓ Branch 0 taken 28605 times.
✗ Branch 1 not taken.
28605 DBUG_TRACE;
7938
2/2
✓ Branch 0 taken 2173 times.
✓ Branch 1 taken 26432 times.
28605 if (ft_handler == nullptr) return -1.0;
7939
7940 26432 TABLE *const table = table_ref->table;
7941
6/6
✓ Branch 0 taken 26384 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 26379 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 26427 times.
26432 if (key != NO_SUCH_KEY && table->has_null_row()) // NULL row from outer join
7942 5 return 0.0;
7943
7944
3/4
✓ Branch 0 taken 26427 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16451 times.
✓ Branch 3 taken 9976 times.
26427 if (get_master()->score_from_index_scan) {
7945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16451 times.
16451 assert(table->file->ft_handler == ft_handler);
7946
1/2
✓ Branch 0 taken 16451 times.
✗ Branch 1 not taken.
16451 return ft_handler->please->get_relevance(ft_handler);
7947 }
7948
7949
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 9928 times.
9976 if (key == NO_SUCH_KEY) {
7950
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 String *a = concat_ws->val_str(&value);
7951
5/6
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 47 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 47 times.
48 if ((null_value = (a == nullptr)) || !a->length()) return 0;
7952
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 return ft_handler->please->find_relevance(ft_handler, (uchar *)a->ptr(),
7953 94 a->length());
7954 }
7955
1/2
✓ Branch 0 taken 9928 times.
✗ Branch 1 not taken.
9928 return ft_handler->please->find_relevance(ft_handler, table->record[0], 0);
7956 28605 }
7957
7958 561 void Item_func_match::print(const THD *thd, String *str,
7959 enum_query_type query_type) const {
7960 561 str->append(STRING_WITH_LEN("(match "));
7961 561 print_args(thd, str, 0, query_type);
7962 561 str->append(STRING_WITH_LEN(" against ("));
7963 561 against->print(thd, str, query_type);
7964
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 436 times.
561 if (flags & FT_BOOL)
7965 125 str->append(STRING_WITH_LEN(" in boolean mode"));
7966
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 424 times.
436 else if (flags & FT_EXPAND)
7967 12 str->append(STRING_WITH_LEN(" with query expansion"));
7968 561 str->append(STRING_WITH_LEN("))"));
7969 561 }
7970
7971 /**
7972 Function sets FT hints(LIMIT, flags) depending on
7973 various join conditions.
7974
7975 @param join Pointer to JOIN object.
7976 @param ft_flag FT flag value.
7977 @param ft_limit Limit value.
7978 @param no_cond true if MATCH is not used in WHERE condition.
7979 */
7980
7981 2344 void Item_func_match::set_hints(JOIN *join, uint ft_flag, ha_rows ft_limit,
7982 bool no_cond) {
7983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2344 times.
2344 assert(!master);
7984
7985
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 2201 times.
2344 if (!join) // used for count() optimization
7986 {
7987 143 hints->set_hint_flag(ft_flag);
7988 143 return;
7989 }
7990
7991 /* skip hints setting if there are aggregates(except of FT_NO_RANKING) */
7992
6/6
✓ Branch 0 taken 2000 times.
✓ Branch 1 taken 201 times.
✓ Branch 2 taken 1993 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 214 times.
✓ Branch 5 taken 1987 times.
4194 if (join->implicit_grouping || !join->group_list.empty() ||
7993
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1987 times.
1993 join->select_distinct) {
7994 /* 'No ranking' is possible even if aggregates are present */
7995
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 83 times.
214 if ((ft_flag & FT_NO_RANKING)) hints->set_hint_flag(FT_NO_RANKING);
7996 214 return;
7997 }
7998
7999 1987 hints->set_hint_flag(ft_flag);
8000
8001 /**
8002 Only one table is used, there is no aggregates,
8003 WHERE condition is a single MATCH expression
8004 (WHERE MATCH(..) or WHERE MATCH(..) [>=,>] value) or
8005 there is no WHERE condition.
8006 */
8007
8/8
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 1958 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1933 times.
✓ Branch 5 taken 25 times.
✓ Branch 6 taken 1943 times.
✓ Branch 7 taken 44 times.
1987 if (join->primary_tables == 1 && (no_cond || is_simple_expression()))
8008 1943 hints->set_hint_limit(ft_limit);
8009 }
8010
8011 /***************************************************************************
8012 System variables
8013 ****************************************************************************/
8014
8015 /**
8016 Return value of an system variable base[.name] as a constant item.
8017
8018 @param pc Current parse context
8019 @param scope Global / session
8020 @param prefix Optional prefix part of the variable name
8021 @param suffix Trivial name of suffix part of the variable name
8022 @param unsafe_for_replication If true and if the variable is written to a
8023 binlog then mark the statement as unsafe.
8024
8025 @note
8026 If component.str = 0 then the variable name is in 'name'
8027
8028 @return
8029 - 0 : error
8030 - # : constant item
8031 */
8032
8033 677902 Item *get_system_variable(Parse_context *pc, enum_var_type scope,
8034 const LEX_CSTRING &prefix, const LEX_CSTRING &suffix,
8035 bool unsafe_for_replication) {
8036 677902 THD *thd = pc->thd;
8037
8038 enum_var_type resolved_scope;
8039 677902 bool written_to_binlog_flag = false;
8040 677749 auto f = [thd, scope, &resolved_scope, &written_to_binlog_flag](
8041 3048346 const System_variable_tracker &, sys_var *v) -> bool {
8042
2/2
✓ Branch 0 taken 339101 times.
✓ Branch 1 taken 338648 times.
677749 if (scope == OPT_DEFAULT) {
8043
2/2
✓ Branch 0 taken 73238 times.
✓ Branch 1 taken 265863 times.
339101 if (v->check_scope(OPT_SESSION)) {
8044 73238 resolved_scope = OPT_SESSION;
8045 } else {
8046 /* As there was no local variable, return the global value */
8047
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 265863 times.
265863 assert(v->check_scope(OPT_GLOBAL));
8048 265863 resolved_scope = OPT_GLOBAL;
8049 }
8050
2/2
✓ Branch 0 taken 337999 times.
✓ Branch 1 taken 649 times.
338648 } else if (v->check_scope(scope)) {
8051 337999 resolved_scope = scope;
8052 } else {
8053
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 622 times.
649 my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), v->name.str,
8054 scope == OPT_GLOBAL ? "SESSION" : "GLOBAL");
8055 649 return true;
8056 }
8057
8058 677100 written_to_binlog_flag = v->is_written_to_binlog(resolved_scope);
8059 677100 v->do_deprecated_warning(thd);
8060 677100 return false;
8061 677902 };
8062 System_variable_tracker var_tracker = System_variable_tracker::make_tracker(
8063
1/2
✓ Branch 0 taken 677902 times.
✗ Branch 1 not taken.
677902 to_string_view(prefix), to_string_view(suffix));
8064
4/6
✓ Branch 0 taken 677903 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 677903 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 803 times.
✓ Branch 5 taken 677100 times.
677902 if (var_tracker.access_system_variable<bool>(thd, f).value_or(true)) {
8065 803 return nullptr;
8066 }
8067
8068
4/4
✓ Branch 0 taken 671023 times.
✓ Branch 1 taken 6077 times.
✓ Branch 2 taken 659919 times.
✓ Branch 3 taken 11104 times.
677100 if (unsafe_for_replication && !written_to_binlog_flag)
8069
1/2
✓ Branch 0 taken 659919 times.
✗ Branch 1 not taken.
659919 thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
8070
8071 677100 thd->lex->set_uncacheable(pc->select, UNCACHEABLE_SIDEEFFECT);
8072
8073
2/4
✓ Branch 0 taken 677100 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 677099 times.
✗ Branch 3 not taken.
677100 return new Item_func_get_system_var(var_tracker, resolved_scope);
8074 677902 }
8075
8076 4922 bool Item_func_row_count::itemize(Parse_context *pc, Item **res) {
8077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4922 times.
4922 if (skip_itemize(res)) return false;
8078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4922 times.
4922 if (super::itemize(pc, res)) return true;
8079
8080 4922 LEX *lex = pc->thd->lex;
8081 4922 lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8082 4922 lex->safe_to_cache_query = false;
8083 4922 return false;
8084 }
8085
8086 246 longlong Item_func_row_count::val_int() {
8087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
246 assert(fixed == 1);
8088 246 THD *thd = current_thd;
8089
8090 246 return thd->get_row_count_func();
8091 }
8092
8093 220340 Item_func_sp::Item_func_sp(const POS &pos, const LEX_STRING &db_name,
8094 const LEX_STRING &fn_name, bool use_explicit_name,
8095 220340 PT_item_list *opt_list)
8096 220340 : Item_func(pos, opt_list) {
8097 /*
8098 Set to false here, which is the default according to SQL standard.
8099 RETURNS NULL ON NULL INPUT can be implemented by modifying this member.
8100 */
8101 220340 null_on_null = false;
8102 220340 set_nullable(true);
8103 220340 set_stored_program();
8104
1/2
✓ Branch 0 taken 220340 times.
✗ Branch 1 not taken.
220340 THD *thd = current_thd;
8105 220340 m_name = new (thd->mem_root)
8106
1/2
✓ Branch 0 taken 220340 times.
✗ Branch 1 not taken.
220340 sp_name(to_lex_cstring(db_name), fn_name, use_explicit_name);
8107 220340 }
8108
8109 220340 bool Item_func_sp::itemize(Parse_context *pc, Item **res) {
8110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 220340 times.
220340 if (skip_itemize(res)) return false;
8111
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 220338 times.
220340 if (super::itemize(pc, res)) return true;
8112
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 220338 times.
220338 if (m_name == nullptr) return true; // OOM
8113
8114 220338 THD *thd = pc->thd;
8115 220338 LEX *lex = thd->lex;
8116
8117 220338 context = lex->current_context();
8118 220338 lex->safe_to_cache_query = false;
8119
8120
2/2
✓ Branch 0 taken 79518 times.
✓ Branch 1 taken 140820 times.
220338 if (m_name->m_db.str == nullptr) {
8121
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 79516 times.
79518 if (thd->lex->copy_db_to(&m_name->m_db.str, &m_name->m_db.length)) {
8122 2 my_error(ER_NO_DB_ERROR, MYF(0));
8123 2 return true;
8124 }
8125 }
8126
8127 220336 m_name->init_qname(thd);
8128
2/4
✓ Branch 0 taken 220336 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 220336 times.
✗ Branch 3 not taken.
220336 sp_add_own_used_routine(lex, thd, Sroutine_hash_entry::FUNCTION, m_name);
8129
8130 220336 return false;
8131 }
8132
8133 322483 void Item_func_sp::cleanup() {
8134
2/2
✓ Branch 0 taken 318366 times.
✓ Branch 1 taken 4117 times.
322483 if (sp_result_field != nullptr) {
8135 318366 sp_result_field->mem_free();
8136 318366 sp_result_field->table->in_use = nullptr;
8137 }
8138 322483 m_sp = nullptr;
8139 322483 Item_func::cleanup();
8140 322483 }
8141
8142 136822 const char *Item_func_sp::func_name() const {
8143
1/2
✓ Branch 0 taken 136822 times.
✗ Branch 1 not taken.
136822 const THD *thd = current_thd;
8144 /* Calculate length to avoid reallocation of string for sure */
8145 136822 size_t len =
8146
2/2
✓ Branch 0 taken 133233 times.
✓ Branch 1 taken 3589 times.
136822 (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
8147 136822 m_name->m_name.length) *
8148 136822 2 + // characters*quoting
8149 136822 2 + // ` and `
8150
2/2
✓ Branch 0 taken 133233 times.
✓ Branch 1 taken 3589 times.
136822 (m_name->m_explicit_name ? 3 : 0) + // '`', '`' and '.' for the db
8151 1 + // end of string
8152 ALIGN_SIZE(1)); // to avoid String reallocation
8153
1/2
✓ Branch 0 taken 136822 times.
✗ Branch 1 not taken.
136822 String qname((char *)thd->mem_root->Alloc(len), len, system_charset_info);
8154
8155 136822 qname.length(0);
8156
2/2
✓ Branch 0 taken 133233 times.
✓ Branch 1 taken 3589 times.
136822 if (m_name->m_explicit_name) {
8157
1/2
✓ Branch 0 taken 133233 times.
✗ Branch 1 not taken.
133233 append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
8158
1/2
✓ Branch 0 taken 133233 times.
✗ Branch 1 not taken.
133233 qname.append('.');
8159 }
8160
1/2
✓ Branch 0 taken 136822 times.
✗ Branch 1 not taken.
136822 append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
8161 273644 return qname.ptr();
8162 136822 }
8163
8164 180166 table_map Item_func_sp::get_initial_pseudo_tables() const {
8165 /*
8166 INNER_TABLE_BIT prevents function from being evaluated in preparation phase.
8167 @todo - make this dependent on READS SQL or MODIFIES SQL.
8168 Due to bug#26422182, a function cannot be executed before tables
8169 are locked, even though it accesses no tables.
8170 */
8171
2/2
✓ Branch 0 taken 151417 times.
✓ Branch 1 taken 28749 times.
180166 return m_deterministic ? INNER_TABLE_BIT : RAND_TABLE_BIT;
8172 }
8173
8174 81 static void my_missing_function_error(const LEX_STRING &token,
8175 const char *func_name) {
8176
5/6
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 80 times.
81 if (token.length && is_lex_native_function(&token))
8177 1 my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
8178 else
8179 80 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
8180 81 }
8181
8182 /**
8183 @brief Initialize the result field by creating a temporary dummy table
8184 and assign it to a newly created field object. Meta data used to
8185 create the field is fetched from the sp_head belonging to the stored
8186 procedure found in the stored procedure function cache.
8187
8188 @note This function should be called from fix_fields to init the result
8189 field. It is some what related to Item_field.
8190
8191 @see Item_field
8192
8193 @param thd A pointer to the session and thread context.
8194
8195 @return Function return error status.
8196 @retval true is returned on an error
8197 @retval false is returned on success.
8198 */
8199
8200 170232 bool Item_func_sp::init_result_field(THD *thd) {
8201 170232 LEX_CSTRING empty_name = {STRING_WITH_LEN("")};
8202
1/2
✓ Branch 0 taken 170232 times.
✗ Branch 1 not taken.
170232 DBUG_TRACE;
8203
8204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170232 times.
170232 assert(m_sp == nullptr);
8205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170232 times.
170232 assert(sp_result_field == nullptr);
8206
8207 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8208
1/2
✓ Branch 0 taken 170232 times.
✗ Branch 1 not taken.
170232 thd, context->view_error_handler, context->view_error_handler_arg);
8209
1/2
✓ Branch 0 taken 170232 times.
✗ Branch 1 not taken.
170232 m_sp = sp_find_routine(thd, enum_sp_type::FUNCTION, m_name,
8210 &thd->sp_func_cache, true);
8211
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 170151 times.
170232 if (m_sp == nullptr) {
8212
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 my_missing_function_error(m_name->m_name, m_name->m_qname.str);
8213 81 return true;
8214 }
8215
8216 170151 m_deterministic = m_sp->m_chistics->detistic;
8217
8218 /*
8219 A Field need to be attached to a Table.
8220 Below we "create" a dummy table by initializing
8221 the needed pointers.
8222 */
8223
2/4
✓ Branch 0 taken 170151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170151 times.
✗ Branch 3 not taken.
170151 TABLE *dummy_table = new (thd->mem_root) TABLE;
8224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170151 times.
170151 if (dummy_table == nullptr) return true;
8225
2/4
✓ Branch 0 taken 170151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170151 times.
✗ Branch 3 not taken.
170151 TABLE_SHARE *share = new (thd->mem_root) TABLE_SHARE;
8226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170151 times.
170151 if (share == nullptr) return true;
8227
8228 170151 dummy_table->s = share;
8229 170151 dummy_table->alias = "";
8230
1/2
✓ Branch 0 taken 170151 times.
✗ Branch 1 not taken.
170151 if (is_nullable()) dummy_table->set_nullable();
8231 170151 dummy_table->in_use = thd;
8232 170151 dummy_table->copy_blobs = true;
8233 170151 share->table_cache_key = empty_name;
8234 170151 share->db = empty_name;
8235 170151 share->table_name = empty_name;
8236
8237 170151 sp_result_field =
8238
1/2
✓ Branch 0 taken 170151 times.
✗ Branch 1 not taken.
170151 m_sp->create_result_field(thd, max_length, item_name.ptr(), dummy_table);
8239 170151 return sp_result_field == nullptr;
8240 170232 }
8241
8242 /**
8243 @brief Initialize local members with values from the Field interface.
8244
8245 @note called from Item::fix_fields.
8246 */
8247
8248 170146 bool Item_func_sp::resolve_type(THD *) {
8249
1/2
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
170146 DBUG_TRACE;
8250
8251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170146 times.
170146 assert(sp_result_field);
8252
1/2
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
170146 set_data_type(sp_result_field->type());
8253
1/2
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
170146 decimals = sp_result_field->decimals();
8254 170146 max_length = sp_result_field->field_length;
8255
1/2
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
170146 collation.set(sp_result_field->charset());
8256 170146 set_nullable(true);
8257 170146 unsigned_flag = sp_result_field->is_flag_set(UNSIGNED_FLAG);
8258
8259 170146 return false;
8260 170146 }
8261
8262 236998 longlong Item_func_sp::val_int() {
8263
2/2
✓ Branch 0 taken 230 times.
✓ Branch 1 taken 236768 times.
236998 if (execute()) return error_int();
8264
2/2
✓ Branch 0 taken 24757 times.
✓ Branch 1 taken 212011 times.
236768 if (null_value) return 0;
8265 212011 return sp_result_field->val_int();
8266 }
8267
8268 156 double Item_func_sp::val_real() {
8269
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 152 times.
156 if (execute()) return error_real();
8270
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 151 times.
152 if (null_value) return 0.0;
8271 151 return sp_result_field->val_real();
8272 }
8273
8274 13 bool Item_func_sp::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) {
8275
5/6
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 12 times.
13 if (execute() || null_value) return true;
8276 12 return sp_result_field->get_date(ltime, fuzzydate);
8277 }
8278
8279 7 bool Item_func_sp::get_time(MYSQL_TIME *ltime) {
8280
3/6
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7 times.
7 if (execute() || null_value) return true;
8281 7 return sp_result_field->get_time(ltime);
8282 }
8283
8284 1227 my_decimal *Item_func_sp::val_decimal(my_decimal *dec_buf) {
8285
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1226 times.
1227 if (execute()) return error_decimal(dec_buf);
8286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1226 times.
1226 if (null_value) return nullptr;
8287 1226 return sp_result_field->val_decimal(dec_buf);
8288 }
8289
8290 66834 String *Item_func_sp::val_str(String *str) {
8291 66834 StringBuffer<STRING_BUFFER_USUAL_SIZE> buf(str->charset());
8292
4/6
✓ Branch 0 taken 66834 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 66813 times.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
66834 if (execute()) return error_str();
8293
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 66689 times.
66813 if (null_value) return nullptr;
8294 /*
8295 result_field will set buf pointing to internal buffer
8296 of the resul_field. Due to this it will change any time
8297 when SP is executed. In order to prevent occasional
8298 corruption of returned value, we make here a copy.
8299 */
8300
1/2
✓ Branch 0 taken 66689 times.
✗ Branch 1 not taken.
66689 sp_result_field->val_str(&buf);
8301
1/2
✓ Branch 0 taken 66689 times.
✗ Branch 1 not taken.
66689 str->copy(buf);
8302 66689 return str;
8303 66834 }
8304
8305 6 bool Item_func_sp::val_json(Json_wrapper *result) {
8306
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (sp_result_field->type() == MYSQL_TYPE_JSON) {
8307
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 if (execute()) return true;
8308
8309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (null_value) return false;
8310
8311 5 Field_json *json_value = down_cast<Field_json *>(sp_result_field);
8312 5 return json_value->val_json(result);
8313 }
8314
8315 /* purecov: begin deadcode */
8316 assert(false);
8317 my_error(ER_INVALID_CAST_TO_JSON, MYF(0));
8318 return error_json();
8319 /* purecov: end */
8320 }
8321
8322 /**
8323 @brief Execute function & store value in field.
8324 Will set null_value properly only for a successful execution.
8325 @return Function returns error status.
8326 @retval false on success.
8327 @retval true if an error occurred.
8328 */
8329
8330 305241 bool Item_func_sp::execute() {
8331
1/2
✓ Branch 0 taken 305241 times.
✗ Branch 1 not taken.
305241 THD *thd = current_thd;
8332
8333 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8334
1/2
✓ Branch 0 taken 305241 times.
✗ Branch 1 not taken.
305241 thd, context->view_error_handler, context->view_error_handler_arg);
8335
8336 // Bind to an instance of the stored function:
8337
2/2
✓ Branch 0 taken 48499 times.
✓ Branch 1 taken 256742 times.
305241 if (m_sp == nullptr) {
8338
1/2
✓ Branch 0 taken 48499 times.
✗ Branch 1 not taken.
48499 m_sp = sp_setup_routine(thd, enum_sp_type::FUNCTION, m_name,
8339 &thd->sp_func_cache);
8340
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 48482 times.
48499 if (m_sp == nullptr) return true;
8341
1/2
✓ Branch 0 taken 48482 times.
✗ Branch 1 not taken.
48482 if (sp_result_field != nullptr) {
8342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48482 times.
48482 assert(sp_result_field->table->in_use == nullptr);
8343 48482 sp_result_field->table->in_use = thd;
8344 }
8345 }
8346
8347 /* Execute function and store the return value in the field. */
8348
8349
3/4
✓ Branch 0 taken 305224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 240 times.
✓ Branch 3 taken 304984 times.
305224 if (execute_impl(thd)) {
8350 240 null_value = true;
8351
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 232 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
240 if (thd->killed) thd->send_kill_message();
8352 240 return true;
8353 }
8354
8355 /* Check that the field (the value) is not NULL. */
8356
1/2
✓ Branch 0 taken 304984 times.
✗ Branch 1 not taken.
304984 null_value = sp_result_field->is_null();
8357
8358 304984 return false;
8359 305241 }
8360
8361 /**
8362 @brief Execute function and store the return value in the field.
8363 Will set null_value properly only for a successful execution.
8364
8365 @note This function was intended to be the concrete implementation of
8366 the interface function execute. This was never realized.
8367
8368 @return The error state.
8369 @retval false on success
8370 @retval true if an error occurred.
8371 */
8372 305224 bool Item_func_sp::execute_impl(THD *thd) {
8373 305224 bool err_status = true;
8374 305224 Sub_statement_state statement_state;
8375 305224 Security_context *save_security_ctx = thd->security_context();
8376 305224 enum enum_sp_data_access access =
8377 305224 (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS)
8378
1/2
✓ Branch 0 taken 305224 times.
✗ Branch 1 not taken.
305224 ? SP_DEFAULT_ACCESS_MAPPING
8379 305224 : m_sp->m_chistics->daccess;
8380
8381
1/2
✓ Branch 0 taken 305224 times.
✗ Branch 1 not taken.
305224 DBUG_TRACE;
8382
8383
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 305071 times.
305224 if (context->security_ctx) {
8384 /* Set view definer security context */
8385 153 thd->set_security_context(context->security_ctx);
8386 }
8387
3/4
✓ Branch 0 taken 305224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 305223 times.
305224 if (sp_check_access(thd)) goto error;
8388
8389 /*
8390 Throw an error if a non-deterministic function is called while
8391 statement-based replication (SBR) is active.
8392 */
8393
8394
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 89325 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
89333 if (!m_deterministic && !trust_function_creators &&
8395
6/8
✓ Branch 0 taken 89333 times.
✓ Branch 1 taken 215890 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 305222 times.
394558 (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
8396 2 (mysql_bin_log.is_open() &&
8397
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 thd->variables.binlog_format == BINLOG_FORMAT_STMT)) {
8398
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
8399 1 goto error;
8400 }
8401
8402 /*
8403 Disable the binlogging if this is not a SELECT statement. If this is a
8404 SELECT, leave binlogging on, so execute_function() code writes the
8405 function call into binlog.
8406 */
8407
1/2
✓ Branch 0 taken 305222 times.
✗ Branch 1 not taken.
305222 thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
8408
1/2
✓ Branch 0 taken 305222 times.
✗ Branch 1 not taken.
305222 err_status = m_sp->execute_function(thd, args, arg_count, sp_result_field);
8409
1/2
✓ Branch 0 taken 305222 times.
✗ Branch 1 not taken.
305222 thd->restore_sub_statement_state(&statement_state);
8410
8411 305224 error:
8412 305224 thd->set_security_context(save_security_ctx);
8413
8414 305224 return err_status;
8415 305224 }
8416
8417 6012 void Item_func_sp::make_field(Send_field *tmp_field) {
8418
1/2
✓ Branch 0 taken 6012 times.
✗ Branch 1 not taken.
6012 DBUG_TRACE;
8419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6012 times.
6012 assert(sp_result_field);
8420
1/2
✓ Branch 0 taken 6012 times.
✗ Branch 1 not taken.
6012 sp_result_field->make_send_field(tmp_field);
8421
1/2
✓ Branch 0 taken 6012 times.
✗ Branch 1 not taken.
6012 if (item_name.is_set()) tmp_field->col_name = item_name.ptr();
8422 6012 }
8423
8424 286699 Item_result Item_func_sp::result_type() const {
8425
1/2
✓ Branch 0 taken 286699 times.
✗ Branch 1 not taken.
286699 DBUG_TRACE;
8426
3/8
✓ Branch 0 taken 286699 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 286699 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 286699 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
286699 DBUG_PRINT("info", ("m_sp = %p", (void *)m_sp));
8427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 286699 times.
286699 assert(sp_result_field);
8428
1/2
✓ Branch 0 taken 286699 times.
✗ Branch 1 not taken.
573398 return sp_result_field->result_type();
8429 286699 }
8430
8431 215 bool Item_func_found_rows::itemize(Parse_context *pc, Item **res) {
8432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
215 if (skip_itemize(res)) return false;
8433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 215 times.
215 if (super::itemize(pc, res)) return true;
8434 215 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8435 215 pc->thd->lex->safe_to_cache_query = false;
8436 215 push_warning(current_thd, Sql_condition::SL_WARNING,
8437 ER_WARN_DEPRECATED_SYNTAX,
8438 215 ER_THD(current_thd, ER_WARN_DEPRECATED_FOUND_ROWS));
8439 215 return false;
8440 }
8441
8442 181 longlong Item_func_found_rows::val_int() {
8443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 181 times.
181 assert(fixed == 1);
8444 181 return current_thd->found_rows();
8445 }
8446
8447 98 Field *Item_func_sp::tmp_table_field(TABLE *) {
8448
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 DBUG_TRACE;
8449
8450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 assert(sp_result_field);
8451 98 return sp_result_field;
8452 98 }
8453
8454 /**
8455 @brief Checks if requested access to function can be granted to user.
8456 If function isn't found yet, it searches function first.
8457 If function can't be found or user don't have requested access
8458 error is raised.
8459
8460 @param thd thread handler
8461
8462 @return Indication if the access was granted or not.
8463 @retval false Access is granted.
8464 @retval true Requested access can't be granted or function doesn't exists.
8465
8466 */
8467
8468 452920 bool Item_func_sp::sp_check_access(THD *thd) {
8469
1/2
✓ Branch 0 taken 452920 times.
✗ Branch 1 not taken.
452920 DBUG_TRACE;
8470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 452920 times.
452920 assert(m_sp);
8471
3/4
✓ Branch 0 taken 452920 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 452919 times.
452920 if (check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str,
8472 false, false))
8473 1 return true;
8474
8475 452919 return false;
8476 452920 }
8477
8478 170261 bool Item_func_sp::fix_fields(THD *thd, Item **ref) {
8479 170261 Security_context *save_security_ctx = thd->security_context();
8480
8481
1/2
✓ Branch 0 taken 170261 times.
✗ Branch 1 not taken.
170261 DBUG_TRACE;
8482
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 170261 times.
170261 assert(fixed == 0);
8483
8484 /*
8485 Checking privileges to execute the function while creating view and
8486 executing the function of select.
8487 */
8488
4/4
✓ Branch 0 taken 147706 times.
✓ Branch 1 taken 22555 times.
✓ Branch 2 taken 53079 times.
✓ Branch 3 taken 117182 times.
317967 if (!thd->lex->is_view_context_analysis() ||
8489
2/2
✓ Branch 0 taken 30524 times.
✓ Branch 1 taken 117182 times.
147706 (thd->lex->sql_command == SQLCOM_CREATE_VIEW)) {
8490
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 52900 times.
53079 if (context->security_ctx) {
8491 /* Set view definer security context */
8492 179 thd->set_security_context(context->security_ctx);
8493 }
8494
8495 /*
8496 Check whether user has execute privilege or not
8497 */
8498
8499 Internal_error_handler_holder<View_error_handler, TABLE_LIST> view_handler(
8500
1/2
✓ Branch 0 taken 53079 times.
✗ Branch 1 not taken.
53079 thd, context->view_error_handler, context->view_error_handler_arg);
8501
8502 106158 bool res = check_routine_access(thd, EXECUTE_ACL, m_name->m_db.str,
8503
1/2
✓ Branch 0 taken 53079 times.
✗ Branch 1 not taken.
53079 m_name->m_name.str, false, false);
8504 53079 thd->set_security_context(save_security_ctx);
8505
8506
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 53050 times.
53079 if (res) return res;
8507
2/2
✓ Branch 0 taken 53050 times.
✓ Branch 1 taken 29 times.
53079 }
8508
8509 /*
8510 We must call init_result_field before Item_func::fix_fields()
8511 to make m_sp and result_field members available to resolve_type(),
8512 which is called from Item_func::fix_fields().
8513 */
8514
3/4
✓ Branch 0 taken 170232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✓ Branch 3 taken 170151 times.
170232 if (init_result_field(thd)) return true;
8515
8516 170151 sp_pcontext *sp_ctx = m_sp->get_root_parsing_context();
8517
8518
3/4
✓ Branch 0 taken 170151 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 170146 times.
170151 if (arg_count != sp_ctx->context_var_count()) {
8519
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "FUNCTION", m_sp->m_qname.str,
8520 sp_ctx->context_var_count(), arg_count);
8521 5 return true;
8522 }
8523
8524
2/4
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 170146 times.
170146 if (Item_func::fix_fields(thd, ref)) return true;
8525
8526
2/2
✓ Branch 0 taken 177124 times.
✓ Branch 1 taken 170146 times.
347270 for (uint i = 0; i < arg_count; i++) {
8527
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 177119 times.
177124 if (args[0]->data_type() == MYSQL_TYPE_INVALID) {
8528
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 sp_variable *var = sp_ctx->find_variable(i);
8529
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (args[0]->propagate_type(
8530 thd,
8531 5 is_numeric_type(var->type)
8532
4/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
12 ? Type_properties(var->type, var->field_def.is_unsigned)
8533 2 : is_string_type(var->type)
8534 ? Type_properties(var->type, var->field_def.charset)
8535 : Type_properties(var->type)))
8536 return true;
8537 }
8538 }
8539
8540
2/2
✓ Branch 0 taken 147696 times.
✓ Branch 1 taken 22450 times.
170146 if (thd->lex->is_view_context_analysis()) {
8541 /*
8542 Here we check privileges of the stored routine only during view
8543 creation, in order to validate the view. A runtime check is
8544 performed in Item_func_sp::execute(), and this method is not
8545 called during context analysis. Notice, that during view
8546 creation we do not infer into stored routine bodies and do not
8547 check privileges of its statements, which would probably be a
8548 good idea especially if the view has SQL SECURITY DEFINER and
8549 the used stored procedure has SQL SECURITY DEFINER.
8550 */
8551
2/4
✓ Branch 0 taken 147696 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 147696 times.
147696 if (sp_check_access(thd)) return true;
8552 /*
8553 Try to set and restore the security context to see whether it's valid
8554 */
8555 Security_context *save_security_context;
8556
2/4
✓ Branch 0 taken 147696 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 147696 times.
147696 if (m_sp->set_security_ctx(thd, &save_security_context)) return true;
8557
1/2
✓ Branch 0 taken 147696 times.
✗ Branch 1 not taken.
147696 m_sp->m_security_ctx.restore_security_context(thd, save_security_context);
8558 }
8559
8560 // Cleanup immediately, thus execute() will always attach to the routine.
8561
1/2
✓ Branch 0 taken 170146 times.
✗ Branch 1 not taken.
170146 cleanup();
8562
8563 170146 return false;
8564 170261 }
8565
8566 9919 void Item_func_sp::update_used_tables() {
8567 9919 Item_func::update_used_tables();
8568
8569 /* This is reset by Item_func::update_used_tables(). */
8570 9919 set_stored_program();
8571 9919 }
8572
8573 101 void Item_func_sp::fix_after_pullout(Query_block *parent_query_block,
8574 Query_block *removed_query_block) {
8575 101 Item_func::fix_after_pullout(parent_query_block, removed_query_block);
8576 101 }
8577
8578 /*
8579 uuid_short handling.
8580
8581 The short uuid is defined as a longlong that contains the following bytes:
8582
8583 Bytes Comment
8584 1 Server_id & 255
8585 4 Startup time of server in seconds
8586 3 Incrementor
8587
8588 This means that an uuid is guaranteed to be unique
8589 even in a replication environment if the following holds:
8590
8591 - The last byte of the server id is unique
8592 - If you between two shutdown of the server don't get more than
8593 an average of 2^24 = 16M calls to uuid_short() per second.
8594 */
8595
8596 ulonglong uuid_value;
8597
8598 12108 void uuid_short_init() {
8599 12108 uuid_value =
8600 12108 ((((ulonglong)server_id) << 56) + (((ulonglong)server_start_time) << 24));
8601 12108 }
8602
8603 77 bool Item_func_uuid_short::itemize(Parse_context *pc, Item **res) {
8604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (skip_itemize(res)) return false;
8605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
77 if (super::itemize(pc, res)) return true;
8606 77 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8607 77 pc->thd->lex->safe_to_cache_query = false;
8608 77 return false;
8609 }
8610
8611 75 longlong Item_func_uuid_short::val_int() {
8612 ulonglong val;
8613 75 mysql_mutex_lock(&LOCK_uuid_generator);
8614 75 val = uuid_value++;
8615 75 mysql_mutex_unlock(&LOCK_uuid_generator);
8616 75 return (longlong)val;
8617 }
8618
8619 6729 bool Item_func_version::itemize(Parse_context *pc, Item **res) {
8620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6729 times.
6729 if (skip_itemize(res)) return false;
8621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6729 times.
6729 if (super::itemize(pc, res)) return true;
8622 6729 pc->thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
8623 6729 return false;
8624 }
8625
8626 /**
8627 Check if schema and table are hidden by NDB engine.
8628
8629 @param thd Thread handle.
8630 @param schema_name Schema name.
8631 @param table_name Table name.
8632
8633 @retval true If schema and table are hidden by NDB.
8634 @retval false If schema and table are not hidden by NDB.
8635 */
8636
8637 26964038 static inline bool is_hidden_by_ndb(THD *thd, String *schema_name,
8638 String *table_name) {
8639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26964038 times.
26964038 if (!strncmp(schema_name->ptr(), "ndb", 3)) {
8640 List<LEX_STRING> list;
8641
8642 // Check if schema is of ndb and if it is hidden by it.
8643 LEX_STRING sch_name = schema_name->lex_string();
8644 list.push_back(&sch_name);
8645 ha_find_files(thd, nullptr, nullptr, nullptr, true, &list);
8646 if (list.elements == 0) {
8647 // Schema is hidden by ndb engine.
8648 return true;
8649 }
8650
8651 // Check if table is hidden by ndb.
8652 if (table_name != nullptr) {
8653 list.clear();
8654 LEX_STRING tbl_name = table_name->lex_string();
8655 list.push_back(&tbl_name);
8656 ha_find_files(thd, schema_name->ptr(), nullptr, nullptr, false, &list);
8657 if (list.elements == 0) {
8658 // Table is hidden by ndb engine.
8659 return true;
8660 }
8661 }
8662 }
8663
8664 26964038 return false;
8665 }
8666
8667 /**
8668 @brief
8669 INFORMATION_SCHEMA picks metadata from DD using system views.
8670 In order for INFORMATION_SCHEMA to skip listing database for which
8671 the user does not have rights, the following internal functions are used.
8672
8673 Syntax:
8674 int CAN_ACCCESS_DATABASE(schema_name);
8675
8676 @returns,
8677 1 - If current user has access.
8678 0 - If not.
8679 */
8680
8681 171741 longlong Item_func_can_access_database::val_int() {
8682
1/2
✓ Branch 0 taken 171741 times.
✗ Branch 1 not taken.
171741 DBUG_TRACE;
8683
8684 // Read schema_name
8685 171741 String schema_name;
8686
1/2
✓ Branch 0 taken 171741 times.
✗ Branch 1 not taken.
171741 String *schema_name_ptr = args[0]->val_str(&schema_name);
8687
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 171738 times.
171741 if (schema_name_ptr == nullptr) {
8688 3 null_value = true;
8689 3 return 0;
8690 }
8691
8692 // Make sure we have safe string to access.
8693
1/2
✓ Branch 0 taken 171738 times.
✗ Branch 1 not taken.
171738 schema_name_ptr->c_ptr_safe();
8694
8695 // Check if schema is hidden.
8696
1/2
✓ Branch 0 taken 171738 times.
✗ Branch 1 not taken.
171738 THD *thd = current_thd;
8697
2/4
✓ Branch 0 taken 171738 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 171738 times.
171738 if (is_hidden_by_ndb(thd, schema_name_ptr, nullptr)) return 0;
8698
8699 // Skip INFORMATION_SCHEMA database
8700
3/4
✓ Branch 0 taken 171738 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28440 times.
✓ Branch 3 taken 143298 times.
171738 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
8701
8702 // Skip PERFORMANCE_SCHEMA database
8703
3/4
✓ Branch 0 taken 143298 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28423 times.
✓ Branch 3 taken 114875 times.
143298 if (is_perfschema_db(schema_name_ptr->ptr())) return 1;
8704
8705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114875 times.
114875 if (lower_case_table_names == 2) {
8706 /*
8707 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
8708 is in lower case.
8709 */
8710 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
8711 }
8712
8713 // Check access
8714 114875 Security_context *sctx = thd->security_context();
8715
8/16
✓ Branch 0 taken 114875 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 114875 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 170 times.
✓ Branch 5 taken 114705 times.
✓ Branch 6 taken 114875 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 114875 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 45 times.
✓ Branch 11 taken 114830 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
115045 if (!(sctx->master_access(schema_name_ptr->ptr()) &
8716 170 (DB_OP_ACLS | SHOW_DB_ACL) ||
8717
6/10
✓ Branch 0 taken 170 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 170 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 170 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 170 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 45 times.
✓ Branch 9 taken 125 times.
170 acl_get(thd, sctx->host().str, sctx->ip().str, sctx->priv_user().str,
8718 170 schema_name_ptr->ptr(), false) ||
8719
2/4
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✗ Branch 3 not taken.
45 !check_grant_db(thd, schema_name_ptr->ptr()))) {
8720 45 return 0;
8721 }
8722
8723 114830 return 1;
8724 171741 }
8725
8726 4966983 static bool check_table_and_trigger_access(Item **args, bool check_trigger_acl,
8727 bool *null_value) {
8728
1/2
✓ Branch 0 taken 4966983 times.
✗ Branch 1 not taken.
4966983 DBUG_TRACE;
8729
8730 // Read schema_name, table_name
8731 4966983 String schema_name;
8732
1/2
✓ Branch 0 taken 4966983 times.
✗ Branch 1 not taken.
4966983 String *schema_name_ptr = args[0]->val_str(&schema_name);
8733 4966983 String table_name;
8734
1/2
✓ Branch 0 taken 4966983 times.
✗ Branch 1 not taken.
4966983 String *table_name_ptr = args[1]->val_str(&table_name);
8735
3/4
✓ Branch 0 taken 4966977 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4966977 times.
4966983 if (schema_name_ptr == nullptr || table_name_ptr == nullptr) {
8736 6 *null_value = true;
8737 6 return false;
8738 }
8739
8740
1/2
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
4966977 const char *sch_name = schema_name_ptr->c_ptr_safe();
8741
1/2
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
4966977 const char *tbl_name = table_name_ptr->c_ptr_safe();
8742
8743 // Check if table is hidden.
8744
1/2
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
4966977 THD *thd = current_thd;
8745
2/4
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4966977 times.
4966977 if (is_hidden_by_ndb(thd, schema_name_ptr, table_name_ptr)) return false;
8746
8747 // Don't show compression dictionary tables in "SHOW TABLES"
8748
2/4
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4966977 times.
✗ Branch 3 not taken.
4966977 if (compression_dict::is_hardcoded(dd::String_type(sch_name),
8749
3/4
✓ Branch 0 taken 4966977 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56559 times.
✓ Branch 3 taken 4910418 times.
9933954 dd::String_type(tbl_name))) {
8750 56559 return false;
8751 }
8752
8753 // Skip INFORMATION_SCHEMA database
8754
3/4
✓ Branch 0 taken 4910418 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25853 times.
✓ Branch 3 taken 4884565 times.
4910418 if (is_infoschema_db(schema_name_ptr->ptr())) return true;
8755
8756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4884565 times.
4884565 if (lower_case_table_names == 2) {
8757 /*
8758 ACL code assumes that in l-c-t-n > 0 modes schema and table names
8759 passed to it are in lower case.
8760 */
8761 schema_name_ptr->length(
8762 my_casedn_str(files_charset_info, schema_name_ptr->ptr()));
8763 table_name_ptr->length(
8764 my_casedn_str(files_charset_info, table_name_ptr->ptr()));
8765 }
8766
8767 // Check access
8768 4884565 ulong db_access = 0;
8769
2/4
✓ Branch 0 taken 4884565 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4884565 times.
4884565 if (check_access(thd, SELECT_ACL, schema_name_ptr->ptr(), &db_access, nullptr,
8770 false, true))
8771 return false;
8772
8773
1/2
✓ Branch 0 taken 4884565 times.
✗ Branch 1 not taken.
4884565 TABLE_LIST table_list;
8774 4884565 table_list.db = schema_name_ptr->ptr();
8775 4884565 table_list.db_length = schema_name_ptr->length();
8776 4884565 table_list.table_name = table_name_ptr->ptr();
8777 4884565 table_list.table_name_length = table_name_ptr->length();
8778 4884565 table_list.grant.privilege = db_access;
8779
8780
2/2
✓ Branch 0 taken 4828146 times.
✓ Branch 1 taken 56419 times.
4884565 if (check_trigger_acl == false) {
8781
2/2
✓ Branch 0 taken 4827180 times.
✓ Branch 1 taken 966 times.
4828146 if (db_access & TABLE_OP_ACLS) return true;
8782
8783 // Check table access
8784
3/4
✓ Branch 0 taken 966 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 859 times.
✓ Branch 3 taken 107 times.
966 if (check_grant(thd, TABLE_OP_ACLS, &table_list, true, 1, true))
8785 859 return false;
8786 } else // Trigger check.
8787 {
8788 // Check trigger access
8789
3/4
✓ Branch 0 taken 56419 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 56391 times.
112838 if (check_trigger_acl &&
8790
3/4
✓ Branch 0 taken 56419 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 56391 times.
56419 check_table_access(thd, TRIGGER_ACL, &table_list, false, 1, true))
8791 28 return false;
8792 }
8793
8794 56498 return true;
8795 4966983 }
8796
8797 /**
8798 @brief
8799 INFORMATION_SCHEMA picks metadata from new DD using system views.
8800 In order for INFORMATION_SCHEMA to skip listing table for which
8801 the user does not have rights, the following UDF's is used.
8802
8803 Syntax:
8804 int CAN_ACCCESS_TABLE(schema_name, table_name);
8805
8806 @returns,
8807 1 - If current user has access.
8808 0 - If not.
8809 */
8810 4910561 longlong Item_func_can_access_table::val_int() {
8811
1/2
✓ Branch 0 taken 4910561 times.
✗ Branch 1 not taken.
4910561 DBUG_TRACE;
8812
8813
3/4
✓ Branch 0 taken 4910561 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4853140 times.
✓ Branch 3 taken 57421 times.
4910561 if (check_table_and_trigger_access(args, false, &null_value)) return 1;
8814
8815 57421 return 0;
8816 4910561 }
8817
8818 /**
8819 @brief
8820 INFORMATION_SCHEMA picks metadata from new DD using system views.
8821 In order for INFORMATION_SCHEMA to skip listing user accpounts for which
8822 the user does not have rights, the following SQL function is used.
8823
8824 Syntax:
8825 int CAN_ACCCESS_USER(user_part, host_part);
8826
8827 @returns,
8828 1 - If current user has access.
8829 0 - If not.
8830
8831 @sa @ref acl_can_access_user
8832 */
8833 139 longlong Item_func_can_access_user::val_int() {
8834
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 DBUG_TRACE;
8835
8836
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 THD *thd = current_thd;
8837 // Read user, host
8838 139 String user_name;
8839
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 String *user_name_ptr = args[0]->val_str(&user_name);
8840 139 String host_name;
8841
1/2
✓ Branch 0 taken 139 times.
✗ Branch 1 not taken.
139 String *host_name_ptr = args[1]->val_str(&host_name);
8842
3/4
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
139 if (host_name_ptr == nullptr || user_name_ptr == nullptr) {
8843 3 null_value = true;
8844 3 return 0;
8845 }
8846
8847 // Make sure we have safe string to access.
8848
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 host_name_ptr->c_ptr_safe();
8849
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 user_name_ptr->c_ptr_safe();
8850 136 MYSQL_LEX_STRING user_str = {const_cast<char *>(user_name_ptr->ptr()),
8851 136 user_name_ptr->length()};
8852 MYSQL_LEX_STRING
8853 136 host_str = {const_cast<char *>(host_name_ptr->ptr()),
8854 136 host_name_ptr->length()};
8855
1/2
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
136 LEX_USER user;
8856
2/4
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
136 if (!LEX_USER::init(&user, thd, &user_str, &host_str)) return 0;
8857
8858
3/4
✓ Branch 0 taken 136 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 86 times.
136 return acl_can_access_user(thd, &user) ? 1 : 0;
8859 139 }
8860
8861 /**
8862 @brief
8863 INFORMATION_SCHEMA picks metadata from new DD using system views. In
8864 order for INFORMATION_SCHEMA to skip listing table for which the user
8865 does not have rights on triggers, the following UDF's is used.
8866
8867 Syntax:
8868 int CAN_ACCCESS_TRIGGER(schema_name, table_name);
8869
8870 @returns,
8871 1 - If current user has access.
8872 0 - If not.
8873 */
8874 56422 longlong Item_func_can_access_trigger::val_int() {
8875
1/2
✓ Branch 0 taken 56422 times.
✗ Branch 1 not taken.
56422 DBUG_TRACE;
8876
8877
3/4
✓ Branch 0 taken 56422 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56391 times.
✓ Branch 3 taken 31 times.
56422 if (check_table_and_trigger_access(args, true, &null_value)) return 1;
8878
8879 31 return 0;
8880 56422 }
8881
8882 /**
8883 @brief
8884 INFORMATION_SCHEMA picks metadata from DD using system views. In
8885 order for INFORMATION_SCHEMA to skip listing routine for which the user
8886 does not have rights, the following UDF's is used.
8887
8888 Syntax:
8889 int CAN_ACCESS_ROUTINE(schema_name, name, type, user, definer,
8890 check_full_access);
8891
8892 @returns,
8893 1 - If current user has access.
8894 0 - If not.
8895 */
8896 3169668 longlong Item_func_can_access_routine::val_int() {
8897
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 DBUG_TRACE;
8898
8899 // Read schema_name, table_name
8900 3169668 String schema_name;
8901 3169668 String routine_name;
8902 3169668 String type;
8903 3169668 String definer;
8904
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 String *schema_name_ptr = args[0]->val_str(&schema_name);
8905
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 String *routine_name_ptr = args[1]->val_str(&routine_name);
8906
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 String *type_ptr = args[2]->val_str(&type);
8907
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 String *definer_ptr = args[3]->val_str(&definer);
8908
1/2
✓ Branch 0 taken 3169668 times.
✗ Branch 1 not taken.
3169668 bool check_full_access = args[4]->val_int();
8909
4/6
✓ Branch 0 taken 3169665 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3169665 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3169665 times.
✗ Branch 5 not taken.
3169668 if (schema_name_ptr == nullptr || routine_name_ptr == nullptr ||
8910
2/4
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3169665 times.
3169665 type_ptr == nullptr || definer_ptr == nullptr || args[4]->null_value) {
8911 3 null_value = true;
8912 3 return 0;
8913 }
8914
8915 // Make strings safe.
8916
1/2
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
3169665 schema_name_ptr->c_ptr_safe();
8917
1/2
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
3169665 routine_name_ptr->c_ptr_safe();
8918
1/2
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
3169665 type_ptr->c_ptr_safe();
8919
1/2
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
3169665 definer_ptr->c_ptr_safe();
8920
8921 3169665 bool is_procedure = (strcmp(type_ptr->ptr(), "PROCEDURE") == 0);
8922
8923 // Skip INFORMATION_SCHEMA database
8924
4/6
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3169665 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2668017 times.
✓ Branch 5 taken 501648 times.
6339330 if (is_infoschema_db(schema_name_ptr->ptr()) ||
8925
3/4
✓ Branch 0 taken 3169665 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2668017 times.
✓ Branch 3 taken 501648 times.
3169665 !my_strcasecmp(system_charset_info, schema_name_ptr->ptr(), "sys"))
8926 2668017 return 1;
8927
8928 /*
8929 Check if user has full access to the routine properties (i.e including
8930 stored routine code), or partial access (i.e to view its other properties).
8931 */
8932
8933 char user_name_holder[USERNAME_LENGTH + 1];
8934 501648 LEX_STRING user_name = {user_name_holder, USERNAME_LENGTH};
8935
8936 char host_name_holder[HOSTNAME_LENGTH + 1];
8937 501648 LEX_STRING host_name = {host_name_holder, HOSTNAME_LENGTH};
8938
8939
1/2
✓ Branch 0 taken 501648 times.
✗ Branch 1 not taken.
501648 parse_user(definer_ptr->ptr(), definer_ptr->length(), user_name.str,
8940 &user_name.length, host_name.str, &host_name.length);
8941
8942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501648 times.
501648 if (lower_case_table_names == 2) {
8943 /*
8944 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
8945 is in lower case.
8946 */
8947 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
8948 }
8949
8950
1/2
✓ Branch 0 taken 501648 times.
✗ Branch 1 not taken.
501648 THD *thd = current_thd;
8951
1/2
✓ Branch 0 taken 501648 times.
✗ Branch 1 not taken.
501648 bool full_access = has_full_view_routine_access(thd, schema_name_ptr->ptr(),
8952 501648 user_name.str, host_name.str);
8953
8954
2/2
✓ Branch 0 taken 250216 times.
✓ Branch 1 taken 251432 times.
501648 if (check_full_access) {
8955
2/2
✓ Branch 0 taken 250178 times.
✓ Branch 1 taken 38 times.
250216 return full_access ? 1 : 0;
8956
7/8
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 251303 times.
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✓ Branch 5 taken 64 times.
✓ Branch 6 taken 65 times.
✓ Branch 7 taken 251367 times.
251561 } else if (!full_access && !has_partial_view_routine_access(
8957 129 thd, schema_name_ptr->ptr(),
8958 129 routine_name_ptr->ptr(), is_procedure)) {
8959 65 return 0;
8960 }
8961
8962 251367 return 1;
8963 3169668 }
8964
8965 /**
8966 @brief
8967 INFORMATION_SCHEMA picks metadata from DD using system views.
8968 In order for INFORMATION_SCHEMA to skip listing event for which
8969 the user does not have rights, the following internal functions are used.
8970
8971 Syntax:
8972 int CAN_ACCCESS_EVENT(schema_name);
8973
8974 @returns,
8975 1 - If current user has access.
8976 0 - If not.
8977 */
8978
8979 1070 longlong Item_func_can_access_event::val_int() {
8980
1/2
✓ Branch 0 taken 1070 times.
✗ Branch 1 not taken.
1070 DBUG_TRACE;
8981
8982 // Read schema_name
8983 1070 String schema_name;
8984
1/2
✓ Branch 0 taken 1070 times.
✗ Branch 1 not taken.
1070 String *schema_name_ptr = args[0]->val_str(&schema_name);
8985
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1067 times.
1070 if (schema_name_ptr == nullptr) {
8986 3 null_value = true;
8987 3 return 0;
8988 }
8989
8990 // Make sure we have safe string to access.
8991
1/2
✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
1067 schema_name_ptr->c_ptr_safe();
8992
8993 // Check if schema is hidden.
8994
1/2
✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
1067 THD *thd = current_thd;
8995
2/4
✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1067 times.
1067 if (is_hidden_by_ndb(thd, schema_name_ptr, nullptr)) return 0;
8996
8997 // Skip INFORMATION_SCHEMA database
8998
3/4
✓ Branch 0 taken 1067 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1065 times.
1067 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
8999
9000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1065 times.
1065 if (lower_case_table_names == 2) {
9001 /*
9002 ACL code assumes that in l-c-t-n > 0 modes schema name passed to it
9003 is in lower case.
9004 */
9005 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
9006 }
9007
9008 // Check access
9009
3/4
✓ Branch 0 taken 1065 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1062 times.
1065 if (check_access(thd, EVENT_ACL, schema_name_ptr->ptr(), nullptr, nullptr,
9010 false, true)) {
9011 3 return 0;
9012 }
9013
9014 1062 return 1;
9015 1070 }
9016
9017 /**
9018 @brief
9019 INFORMATION_SCHEMA picks metadata from DD using system views.
9020 In order for INFORMATION_SCHEMA to skip listing resource groups for which
9021 the user does not have rights, the following internal functions are used.
9022
9023 Syntax:
9024 int CAN_ACCCESS_RESOURCE_GROUP(resource_group_name);
9025
9026 @returns,
9027 1 - If current user has access.
9028 0 - If not.
9029 */
9030
9031 24 longlong Item_func_can_access_resource_group::val_int() {
9032
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 DBUG_TRACE;
9033
9034
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 auto mgr_ptr = resourcegroups::Resource_group_mgr::instance();
9035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!mgr_ptr->resource_group_support()) {
9036 null_value = true;
9037 return false;
9038 }
9039
9040 // Read resource group name.
9041 24 String res_grp_name;
9042
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 String *res_grp_name_ptr = args[0]->val_str(&res_grp_name);
9043
9044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (res_grp_name_ptr == nullptr) {
9045 null_value = true;
9046 return false;
9047 }
9048
9049 // Make sure we have safe string to access.
9050
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 res_grp_name_ptr->c_ptr_safe();
9051
9052 24 MDL_ticket *ticket = nullptr;
9053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (mgr_ptr->acquire_shared_mdl_for_resource_group(
9054
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 current_thd, res_grp_name_ptr->c_ptr(), MDL_EXPLICIT, &ticket, false))
9055 return false;
9056
9057
3/6
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 auto res_grp_ptr = mgr_ptr->get_resource_group(res_grp_name_ptr->c_ptr());
9058 24 longlong result = true;
9059
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (res_grp_ptr != nullptr) {
9060
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 Security_context *sctx = current_thd->security_context();
9061
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (res_grp_ptr->type() == resourcegroups::Type::SYSTEM_RESOURCE_GROUP) {
9062
8/16
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 10 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
16 if (!(sctx->check_access(SUPER_ACL) ||
9063
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_ADMIN"))
9064
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 .first))
9065 4 result = false;
9066 } else {
9067
8/16
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 13 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
17 if (!(sctx->check_access(SUPER_ACL) ||
9068
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_ADMIN"))
9069
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 .first ||
9070
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 sctx->has_global_grant(STRING_WITH_LEN("RESOURCE_GROUP_USER"))
9071
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 .first))
9072 1 result = false;
9073 }
9074 }
9075
2/4
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 mgr_ptr->release_shared_mdl_for_resource_group(current_thd, ticket);
9076
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 return res_grp_ptr != nullptr ? result : false;
9077 24 }
9078
9079 /**
9080 @brief
9081 INFORMATION_SCHEMA picks metadata from DD using system views.
9082 In order for INFORMATION_SCHEMA to skip listing column for which
9083 the user does not have rights, the following UDF's is used.
9084
9085 Syntax:
9086 int CAN_ACCCESS_COLUMN(schema_name,
9087 table_name,
9088 field_name);
9089
9090 @returns,
9091 1 - If current user has access.
9092 0 - If not.
9093 */
9094 21824259 longlong Item_func_can_access_column::val_int() {
9095
1/2
✓ Branch 0 taken 21824259 times.
✗ Branch 1 not taken.
21824259 DBUG_TRACE;
9096
9097 // Read schema_name, table_name
9098 21824259 String schema_name;
9099
1/2
✓ Branch 0 taken 21824259 times.
✗ Branch 1 not taken.
21824259 String *schema_name_ptr = args[0]->val_str(&schema_name);
9100 21824259 String table_name;
9101
1/2
✓ Branch 0 taken 21824259 times.
✗ Branch 1 not taken.
21824259 String *table_name_ptr = args[1]->val_str(&table_name);
9102
3/4
✓ Branch 0 taken 21824256 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21824256 times.
21824259 if (schema_name_ptr == nullptr || table_name_ptr == nullptr) {
9103 3 null_value = true;
9104 3 return 0;
9105 }
9106
9107 // Make sure we have safe string to access.
9108
1/2
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
21824256 schema_name_ptr->c_ptr_safe();
9109
1/2
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
21824256 table_name_ptr->c_ptr_safe();
9110
9111 // Check if table is hidden.
9112
1/2
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
21824256 THD *thd = current_thd;
9113
2/4
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21824256 times.
21824256 if (is_hidden_by_ndb(thd, schema_name_ptr, table_name_ptr)) return 0;
9114
9115 // Read column_name.
9116 21824256 String column_name;
9117
1/2
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
21824256 String *column_name_ptr = args[2]->val_str(&column_name);
9118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21824256 times.
21824256 if (column_name_ptr == nullptr) {
9119 null_value = true;
9120 return 0;
9121 }
9122
9123 // Make sure we have safe string to access.
9124
1/2
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
21824256 column_name_ptr->c_ptr_safe();
9125
9126 // Skip INFORMATION_SCHEMA database
9127
3/4
✓ Branch 0 taken 21824256 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28089 times.
✓ Branch 3 taken 21796167 times.
21824256 if (is_infoschema_db(schema_name_ptr->ptr())) return 1;
9128
9129 // Check access
9130
1/2
✓ Branch 0 taken 21796167 times.
✗ Branch 1 not taken.
21796167 GRANT_INFO grant_info;
9131
9132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21796167 times.
21796167 if (lower_case_table_names == 2) {
9133 /*
9134 ACL code assumes that in l-c-t-n > 0 modes schema and table names
9135 passed to it are in lower case.
9136 */
9137 my_casedn_str(files_charset_info, schema_name_ptr->ptr());
9138 my_casedn_str(files_charset_info, table_name_ptr->ptr());
9139 }
9140
9141
2/4
✓ Branch 0 taken 21796167 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21796167 times.
21796167 if (check_access(thd, SELECT_ACL, schema_name_ptr->ptr(),
9142 &grant_info.privilege, nullptr, false, true))
9143 return 0;
9144
9145 uint col_access =
9146
1/2
✓ Branch 0 taken 21796167 times.
✗ Branch 1 not taken.
21796167 get_column_grant(thd, &grant_info, schema_name_ptr->ptr(),
9147 21796167 table_name_ptr->ptr(), column_name_ptr->ptr()) &
9148 21796167 COL_ACLS;
9149
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 21795860 times.
21796167 if (!col_access) {
9150 307 return 0;
9151 }
9152
9153 21795860 return 1;
9154 21824259 }
9155
9156 /**
9157 @brief
9158 INFORMATION_SCHEMA picks metadata from DD using system views.
9159 In order for INFORMATION_SCHEMA to skip listing view definition
9160 for the user without rights, the following UDF's is used.
9161
9162 Syntax:
9163 int CAN_ACCESS_VIEW(schema_name, view_name, definer, options);
9164
9165 @returns,
9166 1 - If current user has access.
9167 0 - If not.
9168 */
9169 2777971 longlong Item_func_can_access_view::val_int() {
9170
1/2
✓ Branch 0 taken 2777971 times.
✗ Branch 1 not taken.
2777971 DBUG_TRACE;
9171
9172 // Read schema_name, table_name
9173 2777971 String schema_name;
9174 2777971 String table_name;
9175 2777971 String definer;
9176 2777971 String options;
9177
1/2
✓ Branch 0 taken 2777971 times.
✗ Branch 1 not taken.
2777971 String *schema_name_ptr = args[0]->val_str(&schema_name);
9178
1/2
✓ Branch 0 taken 2777971 times.
✗ Branch 1 not taken.
2777971 String *table_name_ptr = args[1]->val_str(&table_name);
9179
1/2
✓ Branch 0 taken 2777971 times.
✗ Branch 1 not taken.
2777971 String *definer_ptr = args[2]->val_str(&definer);
9180
1/2
✓ Branch 0 taken 2777971 times.
✗ Branch 1 not taken.
2777971 String *options_ptr = args[3]->val_str(&options);
9181
4/6
✓ Branch 0 taken 2777968 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2777968 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2777968 times.
✗ Branch 5 not taken.
2777971 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2777968 times.
2777968 definer_ptr == nullptr || options_ptr == nullptr) {
9183 3 null_value = true;
9184 3 return 0;
9185 }
9186
9187 // Make strings safe.
9188
1/2
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
2777968 schema_name_ptr->c_ptr_safe();
9189
1/2
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
2777968 table_name_ptr->c_ptr_safe();
9190
1/2
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
2777968 definer_ptr->c_ptr_safe();
9191
1/2
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
2777968 options_ptr->c_ptr_safe();
9192
9193 // Skip INFORMATION_SCHEMA database
9194
4/6
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2777968 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2777714 times.
✓ Branch 5 taken 254 times.
5555936 if (is_infoschema_db(schema_name_ptr->ptr()) ||
9195
3/4
✓ Branch 0 taken 2777968 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2777714 times.
✓ Branch 3 taken 254 times.
2777968 !my_strcasecmp(system_charset_info, schema_name_ptr->ptr(), "sys"))
9196 2777714 return 1;
9197
9198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
254 if (lower_case_table_names == 2) {
9199 /*
9200 ACL code assumes that in l-c-t-n > 0 modes schema and table names
9201 passed to it are in lower case. Although for view names lowercasing
9202 is not strictly necessary until bug#20356 is fixed we still do it
9203 to be consistent with CAN_ACCESS_TABLE().
9204 */
9205 schema_name_ptr->length(
9206 my_casedn_str(files_charset_info, schema_name_ptr->ptr()));
9207 table_name_ptr->length(
9208 my_casedn_str(files_charset_info, table_name_ptr->ptr()));
9209 }
9210
9211 // Check if view is valid. If view is invalid then push invalid view
9212 // warning.
9213 254 bool is_view_valid = true;
9214 std::unique_ptr<dd::Properties> view_options(
9215
3/6
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 254 times.
✗ Branch 5 not taken.
254 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9216
9217 // Warn if the property string is corrupt.
9218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 254 times.
254 if (!view_options.get()) {
9219 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9220 options_ptr->c_ptr_safe());
9221 assert(false);
9222 return 0;
9223 }
9224
9225
3/6
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 254 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 254 times.
254 if (view_options->get("view_valid", &is_view_valid)) return 0;
9226
9227 // Show warning/error if view is invalid.
9228
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 THD *thd = current_thd;
9229
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 const String db_str(schema_name_ptr->c_ptr_safe(), system_charset_info);
9230
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 const String name_str(table_name_ptr->c_ptr_safe(), system_charset_info);
9231
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 186 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 243 times.
322 if (!is_view_valid &&
9232
3/4
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 57 times.
68 !thd->lex->m_IS_table_stats.check_error_for_key(db_str, name_str)) {
9233 std::string err_message = push_view_warning_or_error(
9234
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 current_thd, schema_name_ptr->ptr(), table_name_ptr->ptr());
9235
9236 /*
9237 Cache the error message, so that we do not show the same error multiple
9238 times.
9239 */
9240
2/4
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
11 thd->lex->m_IS_table_stats.store_error_message(db_str, name_str, nullptr,
9241 err_message.c_str());
9242 11 }
9243
9244 //
9245 // Check if definer user/host has access.
9246 //
9247
9248 254 Security_context *sctx = thd->security_context();
9249
9250 // NOTE: this is a copy/paste from sp_head::set_definer().
9251
9252 char user_name_holder[USERNAME_LENGTH + 1];
9253 254 LEX_STRING user_name = {user_name_holder, USERNAME_LENGTH};
9254
9255 char host_name_holder[HOSTNAME_LENGTH + 1];
9256 254 LEX_STRING host_name = {host_name_holder, HOSTNAME_LENGTH};
9257
9258
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 parse_user(definer_ptr->ptr(), definer_ptr->length(), user_name.str,
9259 &user_name.length, host_name.str, &host_name.length);
9260
9261
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 std::string definer_user(user_name.str, user_name.length);
9262
1/2
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
254 std::string definer_host(host_name.str, host_name.length);
9263
9264
5/6
✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 222 times.
✓ Branch 5 taken 32 times.
476 if (!strcmp(definer_user.c_str(), sctx->priv_user().str) &&
9265
3/6
✓ Branch 0 taken 222 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 222 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
222 !my_strcasecmp(system_charset_info, definer_host.c_str(),
9266 sctx->priv_host().str))
9267 222 return 1;
9268
9269 //
9270 // Check for ACL's
9271 //
9272
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 TABLE_LIST table_list;
9273 32 table_list.db = schema_name_ptr->ptr();
9274 32 table_list.db_length = schema_name_ptr->length();
9275 32 table_list.table_name = table_name_ptr->ptr();
9276 32 table_list.table_name_length = table_name_ptr->length();
9277
9278
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 20 times.
32 if (!check_table_access(thd, (SHOW_VIEW_ACL | SELECT_ACL), &table_list, false,
9279 1, true))
9280 12 return 1;
9281
9282 20 return 0;
9283 2777971 }
9284
9285 /**
9286 Skip hidden tables, columns, indexes and index elements. Additionally,
9287 skip generated invisible primary key(GIPK) and key column when system
9288 variable show_gipk_in_create_table_and_information_schema is set to
9289 OFF.
9290 Do *not* skip hidden tables, columns, indexes and index elements,
9291 when SHOW EXTENDED command are run. GIPK and key column are skipped
9292 even for SHOW EXTENED command.
9293
9294 Syntax:
9295 longlong IS_VISIBLE_DD_OBJECT(type_of_hidden_table [, is_object_hidden
9296 [, object_options]])
9297
9298 @returns,
9299 1 - If dd object is visible
9300 0 - If not visible.
9301 */
9302 24249465 longlong Item_func_is_visible_dd_object::val_int() {
9303
1/2
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
24249465 DBUG_TRACE;
9304
9305
2/4
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 24249465 times.
✗ Branch 3 not taken.
24249465 assert(arg_count > 0 && arg_count <= 3);
9306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24249465 times.
24249465 assert(args[0]->null_value == false);
9307
9308
4/6
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22115239 times.
✓ Branch 3 taken 2134226 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 22115239 times.
24249465 if (args[0]->null_value || (arg_count >= 2 && args[1]->null_value)) {
9309 null_value = true;
9310 return false;
9311 }
9312
9313 24249465 null_value = false;
9314
1/2
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
24249465 THD *thd = current_thd;
9315
9316 auto table_type =
9317
1/2
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
24249465 static_cast<dd::Abstract_table::enum_hidden_type>(args[0]->val_int());
9318
9319 24249465 bool show_table = (table_type == dd::Abstract_table::HT_VISIBLE);
9320
9321 // Make I_S.TABLES show the hidden system view 'show_statistics' for
9322 // testing purpose.
9323
3/4
✓ Branch 0 taken 24249465 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
✓ Branch 3 taken 24249419 times.
24249465 DBUG_EXECUTE_IF("fetch_system_view_definition", { return 1; });
9324
9325
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 24249352 times.
24249419 if (thd->lex->m_extended_show)
9326 67 show_table =
9327
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
67 show_table || (table_type == dd::Abstract_table::HT_HIDDEN_DDL);
9328
9329
6/6
✓ Branch 0 taken 22115239 times.
✓ Branch 1 taken 2134180 times.
✓ Branch 2 taken 11048385 times.
✓ Branch 3 taken 11066854 times.
✓ Branch 4 taken 1226989 times.
✓ Branch 5 taken 11955576 times.
24249419 if (arg_count == 1 || show_table == false) return (show_table ? 1 : 0);
9330
9331 // Skip generated invisible primary key and key columns.
9332
6/8
✓ Branch 0 taken 11066854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11066854 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8877375 times.
✓ Branch 5 taken 2189479 times.
✓ Branch 6 taken 185 times.
✓ Branch 7 taken 11066669 times.
19944229 if (arg_count == 3 && !args[2]->is_null() &&
9333
2/2
✓ Branch 0 taken 185 times.
✓ Branch 1 taken 8877190 times.
8877375 !thd->variables.show_gipk_in_create_table_and_information_schema) {
9334 185 String options;
9335
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 String *options_ptr = args[2]->val_str(&options);
9336
9337
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 if (options_ptr != nullptr) {
9338 // Read options from properties
9339 std::unique_ptr<dd::Properties> p(
9340
3/6
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 185 times.
✗ Branch 5 not taken.
185 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9341
9342
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 if (p.get()) {
9343
4/6
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✓ Branch 5 taken 97 times.
185 if (p->exists("gipk")) {
9344 88 bool gipk_value = false;
9345
2/4
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
88 p->get("gipk", &gipk_value);
9346
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 if (gipk_value) return 0;
9347 }
9348 } else {
9349 // Warn if the property string is corrupt.
9350 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9351 options_ptr->c_ptr_safe());
9352 assert(false);
9353 }
9354
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 88 times.
185 }
9355 /*
9356 Even if object is not a GIPK column/key we still need to check if it is
9357 marked as hidden.
9358 */
9359
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 88 times.
185 }
9360
9361 bool show_non_table_objects;
9362
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 11066711 times.
11066766 if (thd->lex->m_extended_show)
9363 55 show_non_table_objects = true;
9364 else
9365
1/2
✓ Branch 0 taken 11066711 times.
✗ Branch 1 not taken.
11066711 show_non_table_objects = (args[1]->val_bool() == false);
9366
9367
2/2
✓ Branch 0 taken 8899207 times.
✓ Branch 1 taken 2167559 times.
11066766 return show_non_table_objects ? 1 : 0;
9368 24249465 }
9369
9370 /**
9371 Get table statistics from dd::info_schema::get_table_statistics.
9372
9373 @param args List of parameters in following order,
9374
9375 - Schema_name
9376 - Table_name
9377 - Engine_name
9378 - se_private_id
9379 - Hidden_table
9380 - Tablespace_se_private_data
9381 - Table_se_private_data (Used if stype is AUTO_INC)
9382 - Partition name (optional argument).
9383
9384 @param arg_count Number of arguments in 'args'
9385
9386 @param stype Type of statistics that is requested
9387
9388 @param[out] null_value Marked true indicating NULL, if there is no value.
9389
9390 @returns ulonglong representing the statistics requested.
9391 */
9392
9393 465408 static ulonglong get_table_statistics(
9394 Item **args, uint arg_count, dd::info_schema::enum_table_stats_type stype,
9395 bool *null_value) {
9396
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 DBUG_TRACE;
9397 465408 *null_value = false;
9398
9399 // Reads arguments
9400 465408 String schema_name;
9401 465408 String table_name;
9402 465408 String engine_name;
9403 465408 String ts_se_private_data;
9404 465408 String tbl_se_private_data;
9405 465408 String partition_name;
9406 465408 String *partition_name_ptr = nullptr;
9407
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 String *schema_name_ptr = args[0]->val_str(&schema_name);
9408
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 String *table_name_ptr = args[1]->val_str(&table_name);
9409
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 String *engine_name_ptr = args[2]->val_str(&engine_name);
9410
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 bool skip_hidden_table = args[4]->val_int();
9411
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 String *ts_se_private_data_ptr = args[5]->val_str(&ts_se_private_data);
9412
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 ulonglong stat_data = args[6]->val_uint();
9413
1/2
✓ Branch 0 taken 465408 times.
✗ Branch 1 not taken.
465408 ulonglong cached_timestamp = args[7]->val_uint();
9414
9415 465408 String *tbl_se_private_data_ptr = nullptr;
9416
9417 /*
9418 The same native function used by I_S.TABLES is used by I_S.PARTITIONS.
9419 We invoke native function with partition name only with I_S.PARTITIONS
9420 as a last argument. So, we check for argument count below, before
9421 reading partition name.
9422 */
9423
2/2
✓ Branch 0 taken 57406 times.
✓ Branch 1 taken 408002 times.
465408 if (stype == dd::info_schema::enum_table_stats_type::AUTO_INCREMENT) {
9424
1/2
✓ Branch 0 taken 57406 times.
✗ Branch 1 not taken.
57406 tbl_se_private_data_ptr = args[8]->val_str(&tbl_se_private_data);
9425
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 57406 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
57406 if (arg_count == 10) partition_name_ptr = args[9]->val_str(&partition_name);
9426
2/2
✓ Branch 0 taken 6658 times.
✓ Branch 1 taken 401344 times.
408002 } else if (arg_count == 9)
9427
1/2
✓ Branch 0 taken 6658 times.
✗ Branch 1 not taken.
6658 partition_name_ptr = args[8]->val_str(&partition_name);
9428
9429
4/6
✓ Branch 0 taken 465384 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 465384 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 465384 times.
✗ Branch 5 not taken.
465408 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9430
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 465368 times.
465384 engine_name_ptr == nullptr || skip_hidden_table) {
9431 40 *null_value = true;
9432 40 return 0;
9433 }
9434
9435 // Make sure we have safe string to access.
9436
1/2
✓ Branch 0 taken 465368 times.
✗ Branch 1 not taken.
465368 schema_name_ptr->c_ptr_safe();
9437
1/2
✓ Branch 0 taken 465368 times.
✗ Branch 1 not taken.
465368 table_name_ptr->c_ptr_safe();
9438
1/2
✓ Branch 0 taken 465368 times.
✗ Branch 1 not taken.
465368 engine_name_ptr->c_ptr_safe();
9439
9440 // Do not read dynamic stats for I_S tables.
9441
3/4
✓ Branch 0 taken 465368 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 155224 times.
✓ Branch 3 taken 310144 times.
465368 if (is_infoschema_db(schema_name_ptr->ptr())) return 0;
9442
9443 // Read the statistic value from cache.
9444
1/2
✓ Branch 0 taken 310144 times.
✗ Branch 1 not taken.
310144 THD *thd = current_thd;
9445
1/2
✓ Branch 0 taken 310144 times.
✗ Branch 1 not taken.
310144 dd::Object_id se_private_id = (dd::Object_id)args[3]->val_uint();
9446
7/8
✓ Branch 0 taken 1080 times.
✓ Branch 1 taken 309064 times.
✓ Branch 2 taken 68592 times.
✓ Branch 3 taken 241552 times.
✓ Branch 4 taken 6644 times.
✓ Branch 5 taken 303500 times.
✓ Branch 6 taken 310144 times.
✗ Branch 7 not taken.
386460 ulonglong result = thd->lex->m_IS_table_stats.read_stat(
9447 thd, *schema_name_ptr, *table_name_ptr, *engine_name_ptr,
9448
1/2
✓ Branch 0 taken 6644 times.
✗ Branch 1 not taken.
6644 (partition_name_ptr ? partition_name_ptr->c_ptr_safe() : nullptr),
9449 se_private_id,
9450
1/2
✓ Branch 0 taken 68592 times.
✗ Branch 1 not taken.
68592 (ts_se_private_data_ptr ? ts_se_private_data_ptr->c_ptr_safe() : nullptr),
9451
1/2
✓ Branch 0 taken 1080 times.
✗ Branch 1 not taken.
1080 (tbl_se_private_data_ptr ? tbl_se_private_data_ptr->c_ptr_safe()
9452 : nullptr),
9453 stat_data, cached_timestamp, stype);
9454
9455 310144 return result;
9456 465408 }
9457
9458 58651 longlong Item_func_internal_table_rows::val_int() {
9459
1/2
✓ Branch 0 taken 58651 times.
✗ Branch 1 not taken.
58651 DBUG_TRACE;
9460
9461
1/2
✓ Branch 0 taken 58651 times.
✗ Branch 1 not taken.
58651 ulonglong result = get_table_statistics(
9462 args, arg_count, dd::info_schema::enum_table_stats_type::TABLE_ROWS,
9463 &null_value);
9464
9465
4/4
✓ Branch 0 taken 58648 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 58646 times.
58651 if (null_value == false && result == (ulonglong)-1) null_value = true;
9466
9467 58651 return result;
9468 58651 }
9469
9470 58023 longlong Item_func_internal_avg_row_length::val_int() {
9471
1/2
✓ Branch 0 taken 58023 times.
✗ Branch 1 not taken.
58023 DBUG_TRACE;
9472
9473
1/2
✓ Branch 0 taken 58023 times.
✗ Branch 1 not taken.
58023 ulonglong result = get_table_statistics(
9474 args, arg_count,
9475 dd::info_schema::enum_table_stats_type::TABLE_AVG_ROW_LENGTH,
9476 &null_value);
9477 58023 return result;
9478 58023 }
9479
9480 58625 longlong Item_func_internal_data_length::val_int() {
9481
1/2
✓ Branch 0 taken 58625 times.
✗ Branch 1 not taken.
58625 DBUG_TRACE;
9482
9483
1/2
✓ Branch 0 taken 58625 times.
✗ Branch 1 not taken.
58625 ulonglong result = get_table_statistics(
9484 args, arg_count, dd::info_schema::enum_table_stats_type::DATA_LENGTH,
9485 &null_value);
9486 58625 return result;
9487 58625 }
9488
9489 58025 longlong Item_func_internal_max_data_length::val_int() {
9490
1/2
✓ Branch 0 taken 58025 times.
✗ Branch 1 not taken.
58025 DBUG_TRACE;
9491
9492
1/2
✓ Branch 0 taken 58025 times.
✗ Branch 1 not taken.
58025 ulonglong result = get_table_statistics(
9493 args, arg_count, dd::info_schema::enum_table_stats_type::MAX_DATA_LENGTH,
9494 &null_value);
9495 58025 return result;
9496 58025 }
9497
9498 58638 longlong Item_func_internal_index_length::val_int() {
9499
1/2
✓ Branch 0 taken 58638 times.
✗ Branch 1 not taken.
58638 DBUG_TRACE;
9500
9501
1/2
✓ Branch 0 taken 58638 times.
✗ Branch 1 not taken.
58638 ulonglong result = get_table_statistics(
9502 args, arg_count, dd::info_schema::enum_table_stats_type::INDEX_LENGTH,
9503 &null_value);
9504 58638 return result;
9505 58638 }
9506
9507 58020 longlong Item_func_internal_data_free::val_int() {
9508
1/2
✓ Branch 0 taken 58020 times.
✗ Branch 1 not taken.
58020 DBUG_TRACE;
9509
9510
1/2
✓ Branch 0 taken 58020 times.
✗ Branch 1 not taken.
58020 ulonglong result = get_table_statistics(
9511 args, arg_count, dd::info_schema::enum_table_stats_type::DATA_FREE,
9512 &null_value);
9513
9514
3/4
✓ Branch 0 taken 58017 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 58017 times.
58020 if (null_value == false && result == (ulonglong)-1) null_value = true;
9515
9516 58020 return result;
9517 58020 }
9518
9519 57406 longlong Item_func_internal_auto_increment::val_int() {
9520
1/2
✓ Branch 0 taken 57406 times.
✗ Branch 1 not taken.
57406 DBUG_TRACE;
9521
9522
1/2
✓ Branch 0 taken 57406 times.
✗ Branch 1 not taken.
57406 ulonglong result = get_table_statistics(
9523 args, arg_count, dd::info_schema::enum_table_stats_type::AUTO_INCREMENT,
9524 &null_value);
9525
9526
4/4
✓ Branch 0 taken 57387 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 55597 times.
✓ Branch 3 taken 1790 times.
57406 if (null_value == false && result < (ulonglong)1) null_value = true;
9527
9528 57406 return result;
9529 57406 }
9530
9531 58020 longlong Item_func_internal_checksum::val_int() {
9532
1/2
✓ Branch 0 taken 58020 times.
✗ Branch 1 not taken.
58020 DBUG_TRACE;
9533
9534
1/2
✓ Branch 0 taken 58020 times.
✗ Branch 1 not taken.
58020 ulonglong result = get_table_statistics(
9535 args, arg_count, dd::info_schema::enum_table_stats_type::CHECKSUM,
9536 &null_value);
9537
9538
4/4
✓ Branch 0 taken 58017 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 58011 times.
✓ Branch 3 taken 6 times.
58020 if (null_value == false && result == 0) null_value = true;
9539
9540 58020 return result;
9541 58020 }
9542
9543 /**
9544 @brief
9545 INFORMATION_SCHEMA picks metadata from DD using system views.
9546 INFORMATION_SCHEMA.STATISTICS.COMMENT is used to indicate if the indexes are
9547 disabled by ALTER TABLE ... DISABLE KEYS. This property of table is stored
9548 in mysql.tables.options as 'keys_disabled=0/1/'. This internal function
9549 returns value of option 'keys_disabled' for a given table.
9550
9551 Syntax:
9552 int INTERNAL_KEYS_DISABLED(table_options);
9553
9554 @returns,
9555 1 - If keys are disabled.
9556 0 - If not.
9557 */
9558 1577 longlong Item_func_internal_keys_disabled::val_int() {
9559
1/2
✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
1577 DBUG_TRACE;
9560
9561 // Read options.
9562 1577 String options;
9563
1/2
✓ Branch 0 taken 1577 times.
✗ Branch 1 not taken.
1577 String *options_ptr = args[0]->val_str(&options);
9564
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1574 times.
1577 if (options_ptr == nullptr) return 0;
9565
9566 // Read table option from properties
9567 std::unique_ptr<dd::Properties> p(
9568
3/6
✓ Branch 0 taken 1574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1574 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1574 times.
✗ Branch 5 not taken.
1574 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9569
9570 // Warn if the property string is corrupt.
9571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1574 times.
1574 if (!p.get()) {
9572 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9573 options_ptr->c_ptr_safe());
9574 assert(false);
9575 return 0;
9576 }
9577
9578 // Read keys_disabled sub type.
9579 1574 uint keys_disabled = 0;
9580
2/4
✓ Branch 0 taken 1574 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1574 times.
✗ Branch 3 not taken.
1574 p->get("keys_disabled", &keys_disabled);
9581
9582 1574 return keys_disabled;
9583 1577 }
9584
9585 /**
9586 @brief
9587 INFORMATION_SCHEMA picks metadata from DD using system views.
9588 INFORMATION_SCHEMA.STATISTICS.CARDINALITY reads data from SE.
9589
9590 Syntax:
9591 int INTERNAL_INDEX_COLUMN_CARDINALITY(
9592 schema_name,
9593 table_name,
9594 index_name,
9595 column_name,
9596 index_ordinal_position,
9597 column_ordinal_position,
9598 engine,
9599 se_private_id,
9600 is_hidden,
9601 stat_cardinality,
9602 cached_timestamp);
9603
9604 @returns Cardinatily. Or sets null_value to true if cardinality is -1.
9605 */
9606 4737 longlong Item_func_internal_index_column_cardinality::val_int() {
9607
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 DBUG_TRACE;
9608 4737 null_value = false;
9609
9610 // Read arguments
9611 4737 String schema_name;
9612 4737 String table_name;
9613 4737 String index_name;
9614 4737 String column_name;
9615 4737 String engine_name;
9616
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 String *schema_name_ptr = args[0]->val_str(&schema_name);
9617
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 String *table_name_ptr = args[1]->val_str(&table_name);
9618
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 String *index_name_ptr = args[2]->val_str(&index_name);
9619
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 String *column_name_ptr = args[3]->val_str(&column_name);
9620
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 uint index_ordinal_position = args[4]->val_uint();
9621
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 uint column_ordinal_position = args[5]->val_uint();
9622
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 String *engine_name_ptr = args[6]->val_str(&engine_name);
9623
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 dd::Object_id se_private_id = (dd::Object_id)args[7]->val_uint();
9624
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 bool hidden_index = args[8]->val_int();
9625
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 ulonglong stat_cardinality = args[9]->val_uint();
9626
1/2
✓ Branch 0 taken 4737 times.
✗ Branch 1 not taken.
4737 ulonglong cached_timestamp = args[10]->val_uint();
9627
9628 // stat_cardinality and cached_timestamp from mysql.index_stats can be null
9629 // when stat is fetched for 1st time without executing ANALYZE command.
9630
4/6
✓ Branch 0 taken 4734 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4734 times.
✗ Branch 5 not taken.
4737 if (schema_name_ptr == nullptr || table_name_ptr == nullptr ||
9631
2/4
✓ Branch 0 taken 4734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4734 times.
✗ Branch 3 not taken.
4734 index_name_ptr == nullptr || engine_name_ptr == nullptr ||
9632
1/2
✓ Branch 0 taken 4734 times.
✗ Branch 1 not taken.
4734 column_name_ptr == nullptr || args[4]->null_value ||
9633
4/6
✓ Branch 0 taken 4734 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4734 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 4724 times.
4734 args[5]->null_value || args[8]->null_value || hidden_index) {
9634 13 null_value = true;
9635 13 return 0;
9636 }
9637
9638 // Make sure we have safe string to access.
9639
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 schema_name_ptr->c_ptr_safe();
9640
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 table_name_ptr->c_ptr_safe();
9641
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 index_name_ptr->c_ptr_safe();
9642
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 column_name_ptr->c_ptr_safe();
9643
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 engine_name_ptr->c_ptr_safe();
9644
9645 4724 ulonglong result = 0;
9646
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 THD *thd = current_thd;
9647
1/2
✓ Branch 0 taken 4724 times.
✗ Branch 1 not taken.
4724 result = thd->lex->m_IS_table_stats.read_stat(
9648 thd, *schema_name_ptr, *table_name_ptr, *index_name_ptr, nullptr,
9649 *column_name_ptr, index_ordinal_position - 1, column_ordinal_position - 1,
9650 *engine_name_ptr, se_private_id, nullptr, nullptr, stat_cardinality,
9651 cached_timestamp,
9652 dd::info_schema::enum_table_stats_type::INDEX_COLUMN_CARDINALITY);
9653
9654
2/2
✓ Branch 0 taken 2118 times.
✓ Branch 1 taken 2606 times.
4724 if (result == (ulonglong)-1) null_value = true;
9655
9656 4724 return result;
9657 4737 }
9658
9659 /**
9660 Retrieve tablespace statistics from SE
9661
9662 @param thd The current thread.
9663
9664 @param args List of parameters in following order,
9665
9666 - Tablespace_name
9667 - Engine_name
9668 - Tablespace_se_private_data
9669
9670 @param[out] null_value Marked true indicating NULL, if there is no value.
9671 */
9672
9673 550913 void retrieve_tablespace_statistics(THD *thd, Item **args, bool *null_value) {
9674
1/2
✓ Branch 0 taken 550913 times.
✗ Branch 1 not taken.
550913 DBUG_TRACE;
9675 550913 *null_value = false;
9676
9677 // Reads arguments
9678 550913 String tablespace_name;
9679
1/2
✓ Branch 0 taken 550913 times.
✗ Branch 1 not taken.
550913 String *tablespace_name_ptr = args[0]->val_str(&tablespace_name);
9680 550913 String file_name;
9681
1/2
✓ Branch 0 taken 550913 times.
✗ Branch 1 not taken.
550913 String *file_name_ptr = args[1]->val_str(&file_name);
9682 550913 String engine_name;
9683
1/2
✓ Branch 0 taken 550913 times.
✗ Branch 1 not taken.
550913 String *engine_name_ptr = args[2]->val_str(&engine_name);
9684 550913 String ts_se_private_data;
9685
1/2
✓ Branch 0 taken 550913 times.
✗ Branch 1 not taken.
550913 String *ts_se_private_data_ptr = args[3]->val_str(&ts_se_private_data);
9686
9687
4/6
✓ Branch 0 taken 550883 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 550883 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 550883 times.
550913 if (tablespace_name_ptr == nullptr || file_name_ptr == nullptr ||
9688 engine_name_ptr == nullptr) {
9689 30 *null_value = true;
9690 30 return;
9691 }
9692
9693 // Make sure we have safe string to access.
9694
1/2
✓ Branch 0 taken 550883 times.
✗ Branch 1 not taken.
550883 tablespace_name_ptr->c_ptr_safe();
9695
1/2
✓ Branch 0 taken 550883 times.
✗ Branch 1 not taken.
550883 file_name_ptr->c_ptr_safe();
9696
1/2
✓ Branch 0 taken 550883 times.
✗ Branch 1 not taken.
550883 engine_name_ptr->c_ptr_safe();
9697
9698 // Read the statistic value from cache.
9699
4/6
✓ Branch 0 taken 550883 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 550883 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 332 times.
✓ Branch 5 taken 550551 times.
1101766 if (thd->lex->m_IS_tablespace_stats.read_stat(
9700 thd, *tablespace_name_ptr, *file_name_ptr, *engine_name_ptr,
9701
1/2
✓ Branch 0 taken 550883 times.
✗ Branch 1 not taken.
550883 (ts_se_private_data_ptr ? ts_se_private_data_ptr->c_ptr_safe()
9702 : nullptr)))
9703 332 *null_value = true;
9704
10/10
✓ Branch 0 taken 550883 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 550883 times.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 550883 times.
✓ Branch 5 taken 30 times.
✓ Branch 6 taken 550883 times.
✓ Branch 7 taken 30 times.
✓ Branch 8 taken 550883 times.
✓ Branch 9 taken 30 times.
551033 }
9705
9706 18100 longlong Item_func_internal_tablespace_id::val_int() {
9707
1/2
✓ Branch 0 taken 18100 times.
✗ Branch 1 not taken.
18100 DBUG_TRACE;
9708 18100 ulonglong result = -1;
9709
9710
1/2
✓ Branch 0 taken 18100 times.
✗ Branch 1 not taken.
18100 THD *thd = current_thd;
9711
1/2
✓ Branch 0 taken 18100 times.
✗ Branch 1 not taken.
18100 retrieve_tablespace_statistics(thd, args, &null_value);
9712
2/2
✓ Branch 0 taken 17766 times.
✓ Branch 1 taken 334 times.
18100 if (null_value == false) {
9713
1/2
✓ Branch 0 taken 17766 times.
✗ Branch 1 not taken.
17766 thd->lex->m_IS_tablespace_stats.get_stat(
9714 dd::info_schema::enum_tablespace_stats_type::TS_ID, &result);
9715 17766 return result;
9716 }
9717
9718 334 return result;
9719 18100 }
9720
9721 2 longlong Item_func_internal_tablespace_logfile_group_number::val_int() {
9722
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 DBUG_TRACE;
9723 2 ulonglong result = -1;
9724
9725
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 THD *thd = current_thd;
9726
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 retrieve_tablespace_statistics(thd, args, &null_value);
9727
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (null_value == false) {
9728
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->lex->m_IS_tablespace_stats.get_stat(
9729 dd::info_schema::enum_tablespace_stats_type::TS_LOGFILE_GROUP_NUMBER,
9730 &result);
9731
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (result == (ulonglong)-1) null_value = true;
9732
9733 2 return result;
9734 }
9735
9736 return result;
9737 2 }
9738
9739 29 longlong Item_func_internal_tablespace_free_extents::val_int() {
9740
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 DBUG_TRACE;
9741 29 ulonglong result = -1;
9742
9743
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 THD *thd = current_thd;
9744
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 retrieve_tablespace_statistics(thd, args, &null_value);
9745
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 3 times.
29 if (null_value == false) {
9746
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 thd->lex->m_IS_tablespace_stats.get_stat(
9747 dd::info_schema::enum_tablespace_stats_type::TS_FREE_EXTENTS, &result);
9748 26 return result;
9749 }
9750
9751 3 return result;
9752 29 }
9753
9754 29 longlong Item_func_internal_tablespace_total_extents::val_int() {
9755
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 DBUG_TRACE;
9756 29 ulonglong result = -1;
9757
9758
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 THD *thd = current_thd;
9759
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 retrieve_tablespace_statistics(thd, args, &null_value);
9760
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 3 times.
29 if (null_value == false) {
9761
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 thd->lex->m_IS_tablespace_stats.get_stat(
9762 dd::info_schema::enum_tablespace_stats_type::TS_TOTAL_EXTENTS, &result);
9763 26 return result;
9764 }
9765
9766 3 return result;
9767 29 }
9768
9769 45 longlong Item_func_internal_tablespace_extent_size::val_int() {
9770
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 DBUG_TRACE;
9771 45 ulonglong result = -1;
9772
9773
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 THD *thd = current_thd;
9774
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 retrieve_tablespace_statistics(thd, args, &null_value);
9775
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3 times.
45 if (null_value == false) {
9776
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 thd->lex->m_IS_tablespace_stats.get_stat(
9777 dd::info_schema::enum_tablespace_stats_type::TS_EXTENT_SIZE, &result);
9778 42 return result;
9779 }
9780
9781 3 return result;
9782 45 }
9783
9784 32 longlong Item_func_internal_tablespace_initial_size::val_int() {
9785
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 DBUG_TRACE;
9786 32 ulonglong result = -1;
9787
9788
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 THD *thd = current_thd;
9789
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 retrieve_tablespace_statistics(thd, args, &null_value);
9790
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 3 times.
32 if (null_value == false) {
9791
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 thd->lex->m_IS_tablespace_stats.get_stat(
9792 dd::info_schema::enum_tablespace_stats_type::TS_INITIAL_SIZE, &result);
9793 29 return result;
9794 }
9795
9796 3 return result;
9797 32 }
9798
9799 45 longlong Item_func_internal_tablespace_maximum_size::val_int() {
9800
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 DBUG_TRACE;
9801 45 ulonglong result = -1;
9802
9803
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 THD *thd = current_thd;
9804
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 retrieve_tablespace_statistics(thd, args, &null_value);
9805
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3 times.
45 if (null_value == false) {
9806
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 thd->lex->m_IS_tablespace_stats.get_stat(
9807 dd::info_schema::enum_tablespace_stats_type::TS_MAXIMUM_SIZE, &result);
9808
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 if (result == (ulonglong)-1) null_value = true;
9809
9810 42 return result;
9811 }
9812
9813 3 return result;
9814 45 }
9815
9816 35 longlong Item_func_internal_tablespace_autoextend_size::val_int() {
9817
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 DBUG_TRACE;
9818 35 ulonglong result = -1;
9819
9820
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 THD *thd = current_thd;
9821
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 retrieve_tablespace_statistics(thd, args, &null_value);
9822
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 3 times.
35 if (null_value == false) {
9823
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 thd->lex->m_IS_tablespace_stats.get_stat(
9824 dd::info_schema::enum_tablespace_stats_type::TS_AUTOEXTEND_SIZE,
9825 &result);
9826 32 return result;
9827 }
9828
9829 3 return result;
9830 35 }
9831
9832 2 longlong Item_func_internal_tablespace_version::val_int() {
9833
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 DBUG_TRACE;
9834 2 ulonglong result = -1;
9835
9836
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 THD *thd = current_thd;
9837
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 retrieve_tablespace_statistics(thd, args, &null_value);
9838
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (null_value == false) {
9839
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 thd->lex->m_IS_tablespace_stats.get_stat(
9840 dd::info_schema::enum_tablespace_stats_type::TS_VERSION, &result);
9841
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (result == (ulonglong)-1) null_value = true;
9842
9843 2 return result;
9844 }
9845
9846 return result;
9847 2 }
9848
9849 29 longlong Item_func_internal_tablespace_data_free::val_int() {
9850
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 DBUG_TRACE;
9851 29 ulonglong result = -1;
9852
9853
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 THD *thd = current_thd;
9854
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 retrieve_tablespace_statistics(thd, args, &null_value);
9855
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 3 times.
29 if (null_value == false) {
9856
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 thd->lex->m_IS_tablespace_stats.get_stat(
9857 dd::info_schema::enum_tablespace_stats_type::TS_DATA_FREE, &result);
9858 26 return result;
9859 }
9860
9861 3 return result;
9862 29 }
9863
9864 6729 Item_func_version::Item_func_version(const POS &pos)
9865 13458 : Item_static_string_func(pos, NAME_STRING("version()"), server_version,
9866 strlen(server_version), system_charset_info,
9867
1/2
✓ Branch 0 taken 6729 times.
✗ Branch 1 not taken.
6729 DERIVATION_SYSCONST) {}
9868
9869 /*
9870 Syntax:
9871 string get_dd_char_length()
9872 */
9873 19871160 longlong Item_func_internal_dd_char_length::val_int() {
9874
1/2
✓ Branch 0 taken 19871160 times.
✗ Branch 1 not taken.
19871160 DBUG_TRACE;
9875 19871160 null_value = false;
9876
9877
1/2
✓ Branch 0 taken 19871160 times.
✗ Branch 1 not taken.
19871160 dd::enum_column_types col_type = (dd::enum_column_types)args[0]->val_int();
9878
1/2
✓ Branch 0 taken 19871160 times.
✗ Branch 1 not taken.
19871160 uint field_length = args[1]->val_int();
9879 19871160 String cs_name;
9880
1/2
✓ Branch 0 taken 19871160 times.
✗ Branch 1 not taken.
19871160 String *cs_name_ptr = args[2]->val_str(&cs_name);
9881
1/2
✓ Branch 0 taken 19871160 times.
✗ Branch 1 not taken.
19871160 uint flag = args[3]->val_int();
9882
9883 // Stop if we found a NULL argument.
9884
4/6
✓ Branch 0 taken 17926609 times.
✓ Branch 1 taken 1944551 times.
✓ Branch 2 taken 17926609 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17926609 times.
✗ Branch 5 not taken.
19871160 if (args[0]->null_value || args[1]->null_value || cs_name_ptr == nullptr ||
9885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17926609 times.
17926609 args[3]->null_value) {
9886 1944551 null_value = true;
9887 1944551 return 0;
9888 }
9889
9890 // Read character set.
9891
2/4
✓ Branch 0 taken 17926609 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17926609 times.
✗ Branch 3 not taken.
17926609 CHARSET_INFO *cs = get_charset_by_name(cs_name_ptr->c_ptr_safe(), MYF(0));
9892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17926609 times.
17926609 if (!cs) {
9893 null_value = true;
9894 return 0;
9895 }
9896
9897 // Check data types for getting info
9898
1/2
✓ Branch 0 taken 17926609 times.
✗ Branch 1 not taken.
17926609 enum_field_types field_type = dd_get_old_field_type(col_type);
9899 17926609 bool blob_flag = is_blob(field_type);
9900
6/6
✓ Branch 0 taken 15200547 times.
✓ Branch 1 taken 2726062 times.
✓ Branch 2 taken 11530265 times.
✓ Branch 3 taken 3670282 times.
✓ Branch 4 taken 11307523 times.
✓ Branch 5 taken 222742 times.
17926609 if (!blob_flag && field_type != MYSQL_TYPE_ENUM &&
9901
2/2
✓ Branch 0 taken 9557074 times.
✓ Branch 1 taken 1750449 times.
11307523 field_type != MYSQL_TYPE_SET &&
9902
2/2
✓ Branch 0 taken 5994956 times.
✓ Branch 1 taken 3562118 times.
9557074 field_type != MYSQL_TYPE_VARCHAR && // For varbinary type
9903 field_type != MYSQL_TYPE_STRING) // For binary type
9904 {
9905 5994956 null_value = true;
9906 5994956 return 0;
9907 }
9908
9909
2/4
✓ Branch 0 taken 11931653 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11931653 times.
✗ Branch 3 not taken.
23863306 std::ostringstream oss("");
9910
5/6
✓ Branch 0 taken 2335060 times.
✓ Branch 1 taken 140 times.
✓ Branch 2 taken 222598 times.
✓ Branch 3 taken 168264 times.
✓ Branch 4 taken 9205591 times.
✗ Branch 5 not taken.
11931653 switch (field_type) {
9911 2335060 case MYSQL_TYPE_BLOB:
9912 2335060 field_length = 65535;
9913 2335060 break;
9914 140 case MYSQL_TYPE_TINY_BLOB:
9915 140 field_length = 255;
9916 140 break;
9917 222598 case MYSQL_TYPE_MEDIUM_BLOB:
9918 222598 field_length = 16777215;
9919 222598 break;
9920 168264 case MYSQL_TYPE_LONG_BLOB:
9921 168264 field_length = 4294967295;
9922 168264 break;
9923 9205591 case MYSQL_TYPE_ENUM:
9924 case MYSQL_TYPE_SET:
9925 case MYSQL_TYPE_VAR_STRING:
9926 case MYSQL_TYPE_VARCHAR:
9927 case MYSQL_TYPE_STRING:
9928 9205591 break;
9929 default:
9930 break;
9931 }
9932
9933
4/4
✓ Branch 0 taken 5965833 times.
✓ Branch 1 taken 5965820 times.
✓ Branch 2 taken 5965117 times.
✓ Branch 3 taken 716 times.
11931653 if (!flag && field_length) {
9934
2/2
✓ Branch 0 taken 1363031 times.
✓ Branch 1 taken 4602086 times.
5965117 if (blob_flag)
9935 1363031 return field_length / cs->mbminlen;
9936 else
9937 4602086 return field_length / cs->mbmaxlen;
9938
4/4
✓ Branch 0 taken 5965820 times.
✓ Branch 1 taken 716 times.
✓ Branch 2 taken 5965104 times.
✓ Branch 3 taken 716 times.
5966536 } else if (flag && field_length) {
9939 5965104 return field_length;
9940 }
9941
9942 1432 return 0;
9943 19871160 }
9944
9945 2094187 longlong Item_func_internal_get_view_warning_or_error::val_int() {
9946
1/2
✓ Branch 0 taken 2094187 times.
✗ Branch 1 not taken.
2094187 DBUG_TRACE;
9947
9948 2094187 String schema_name;
9949 2094187 String table_name;
9950 2094187 String table_type;
9951
1/2
✓ Branch 0 taken 2094187 times.
✗ Branch 1 not taken.
2094187 String *schema_name_ptr = args[0]->val_str(&schema_name);
9952
1/2
✓ Branch 0 taken 2094187 times.
✗ Branch 1 not taken.
2094187 String *table_name_ptr = args[1]->val_str(&table_name);
9953
1/2
✓ Branch 0 taken 2094187 times.
✗ Branch 1 not taken.
2094187 String *table_type_ptr = args[2]->val_str(&table_type);
9954
9955
4/6
✓ Branch 0 taken 2094184 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2094184 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2094184 times.
2094187 if (table_type_ptr == nullptr || schema_name_ptr == nullptr ||
9956 table_name_ptr == nullptr) {
9957 3 return 0;
9958 }
9959
9960 2094184 String options;
9961
1/2
✓ Branch 0 taken 2094184 times.
✗ Branch 1 not taken.
2094184 String *options_ptr = args[3]->val_str(&options);
9962
6/8
✓ Branch 0 taken 2094184 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14629 times.
✓ Branch 3 taken 2079555 times.
✓ Branch 4 taken 14629 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14629 times.
✓ Branch 7 taken 2079555 times.
2094184 if (strcmp(table_type_ptr->c_ptr_safe(), "VIEW") == 0 &&
9963 options_ptr != nullptr) {
9964 14629 bool is_view_valid = true;
9965 std::unique_ptr<dd::Properties> view_options(
9966
3/6
✓ Branch 0 taken 14629 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14629 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14629 times.
✗ Branch 5 not taken.
14629 dd::Properties::parse_properties(options_ptr->c_ptr_safe()));
9967
9968 // Warn if the property string is corrupt.
9969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14629 times.
14629 if (!view_options.get()) {
9970 LogErr(WARNING_LEVEL, ER_WARN_PROPERTY_STRING_PARSE_FAILED,
9971 options_ptr->c_ptr_safe());
9972 assert(false);
9973 return 0;
9974 }
9975
9976 // Return 0 if get_bool() or push_view_warning_or_error() fails
9977
3/6
✓ Branch 0 taken 14629 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14629 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14629 times.
14629 if (view_options->get("view_valid", &is_view_valid)) return 0;
9978
9979
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14613 times.
14629 if (is_view_valid == false) {
9980
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 push_view_warning_or_error(current_thd, schema_name_ptr->c_ptr_safe(),
9981
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 table_name_ptr->c_ptr_safe());
9982 16 return 0;
9983 }
9984
2/2
✓ Branch 0 taken 14613 times.
✓ Branch 1 taken 16 times.
14629 }
9985
9986 2094168 return 1;
9987 2094187 }
9988
9989 /**
9990 @brief
9991 INFORMATION_SCHEMA picks metadata from DD using system views.
9992 INFORMATION_SCHEMA.STATISTICS.SUB_PART represents index sub part length.
9993 This internal function is used to get index sub part length.
9994
9995 Syntax:
9996 int GET_DD_INDEX_SUB_PART_LENGTH(
9997 index_column_usage_length,
9998 column_type,
9999 column_length,
10000 column_collation_id,
10001 index_type);
10002
10003 @returns Index sub part length.
10004 */
10005 4479 longlong Item_func_get_dd_index_sub_part_length::val_int() {
10006
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 DBUG_TRACE;
10007 4479 null_value = true;
10008
10009 // Read arguments
10010
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 uint key_part_length = args[0]->val_int();
10011 dd::enum_column_types col_type =
10012
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 static_cast<dd::enum_column_types>(args[1]->val_int());
10013
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 uint column_length = args[2]->val_int();
10014
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 uint csid = args[3]->val_int();
10015 dd::Index::enum_index_type idx_type =
10016
1/2
✓ Branch 0 taken 4479 times.
✗ Branch 1 not taken.
4479 static_cast<dd::Index::enum_index_type>(args[4]->val_int());
10017
4/6
✓ Branch 0 taken 4466 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 4466 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4466 times.
✗ Branch 5 not taken.
4479 if (args[0]->null_value || args[1]->null_value || args[2]->null_value ||
10018
2/4
✓ Branch 0 taken 4466 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4466 times.
4466 args[3]->null_value || args[4]->null_value)
10019 13 return 0;
10020
10021 // Read server col_type and check if we have key part.
10022
1/2
✓ Branch 0 taken 4466 times.
✗ Branch 1 not taken.
4466 enum_field_types field_type = dd_get_old_field_type(col_type);
10023
3/4
✓ Branch 0 taken 4466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2383 times.
✓ Branch 3 taken 2083 times.
4466 if (!Field::type_can_have_key_part(field_type)) return 0;
10024
10025 // Calculate the key length for the column. Note that we pass inn dummy values
10026 // for "decimals", "is_unsigned" and "elements" since none of those arguments
10027 // will affect the key length for any of the data types that can have a prefix
10028 // index (see Field::type_can_have_key_part above).
10029 uint32 column_key_length =
10030
1/2
✓ Branch 0 taken 2083 times.
✗ Branch 1 not taken.
2083 calc_key_length(field_type, column_length, 0, false, 0);
10031
10032 // Read column charset id from args[3]
10033 2083 const CHARSET_INFO *column_charset = &my_charset_latin1;
10034
1/2
✓ Branch 0 taken 2083 times.
✗ Branch 1 not taken.
2083 if (csid) {
10035
1/2
✓ Branch 0 taken 2083 times.
✗ Branch 1 not taken.
2083 column_charset = get_charset(csid, MYF(0));
10036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2083 times.
2083 assert(column_charset);
10037 }
10038
10039
4/4
✓ Branch 0 taken 2054 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 223 times.
✓ Branch 3 taken 1831 times.
2083 if ((idx_type != dd::Index::IT_FULLTEXT) &&
10040 (key_part_length != column_key_length)) {
10041 223 longlong sub_part_length = key_part_length / column_charset->mbmaxlen;
10042 223 null_value = false;
10043 223 return sub_part_length;
10044 }
10045
10046 1860 return 0;
10047 4479 }
10048
10049 /**
10050 @brief
10051 Internal function used by INFORMATION_SCHEMA implementation to check
10052 if a role is a mandatory role.
10053
10054 Syntax:
10055 int INTERNAL_IS_MANDATORY_ROLE(role_user, role_host);
10056
10057 @returns,
10058 1 - If the role is mandatory.
10059 0 - If not.
10060 */
10061
10062 158 longlong Item_func_internal_is_mandatory_role::val_int() {
10063
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 DBUG_TRACE;
10064
10065 // Read schema_name
10066 158 String role_name;
10067
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 String *role_name_ptr = args[0]->val_str(&role_name);
10068 158 String role_host;
10069
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 String *role_host_ptr = args[1]->val_str(&role_host);
10070
3/4
✓ Branch 0 taken 155 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 155 times.
158 if (role_name_ptr == nullptr || role_host_ptr == nullptr) {
10071 3 null_value = true;
10072 3 return 0;
10073 }
10074
10075 // Create Auth_id for ID being searched.
10076 LEX_CSTRING lex_user;
10077
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 lex_user.str = role_name_ptr->c_ptr_safe();
10078 155 lex_user.length = role_name_ptr->length();
10079
10080 LEX_CSTRING lex_host;
10081
1/2
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
155 lex_host.str = role_host_ptr->c_ptr_safe();
10082 155 lex_host.length = role_host_ptr->length();
10083
10084 155 bool is_mandatory{false};
10085
3/4
✓ Branch 0 taken 155 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 154 times.
155 if (is_mandatory_role(lex_user, lex_host, &is_mandatory)) {
10086 4 push_warning_printf(
10087
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 current_thd, Sql_condition::SL_WARNING,
10088 ER_FAILED_TO_DETERMINE_IF_ROLE_IS_MANDATORY,
10089
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 ER_THD(current_thd, ER_FAILED_TO_DETERMINE_IF_ROLE_IS_MANDATORY),
10090 lex_user.str, lex_host.str);
10091 }
10092
10093 155 return is_mandatory;
10094 158 }
10095
10096 /**
10097 @brief
10098 Internal function used by INFORMATION_SCHEMA implementation to check
10099 if a role enabled.
10100
10101 Syntax:
10102 int INTERNAL_IS_ENABLED_ROLE(role_user, role_host);
10103
10104 @returns,
10105 1 - If the role is enabled.
10106 0 - If not.
10107 */
10108
10109 438 longlong Item_func_internal_is_enabled_role::val_int() {
10110
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 DBUG_TRACE;
10111
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 THD *thd = current_thd;
10112
10113 // Read schema_name
10114 438 String role_name;
10115
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 String *role_name_ptr = args[0]->val_str(&role_name);
10116 438 String role_host;
10117
1/2
✓ Branch 0 taken 438 times.
✗ Branch 1 not taken.
438 String *role_host_ptr = args[1]->val_str(&role_host);
10118
3/4
✓ Branch 0 taken 435 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 435 times.
438 if (role_name_ptr == nullptr || role_host_ptr == nullptr) {
10119 3 null_value = true;
10120 3 return 0;
10121 }
10122
10123
3/4
✓ Branch 0 taken 435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 199 times.
✓ Branch 3 taken 236 times.
435 if (thd->m_main_security_ctx.get_active_roles()->size() == 0) return 0;
10124
10125 // Create Auth_id for ID being searched.
10126 LEX_CSTRING lex_user;
10127
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 lex_user.str = role_name_ptr->c_ptr_safe();
10128 236 lex_user.length = role_name_ptr->length();
10129
10130 LEX_CSTRING lex_host;
10131
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 lex_host.str = role_host_ptr->c_ptr_safe();
10132 236 lex_host.length = role_host_ptr->length();
10133
10134 // Match the ID and return true if found.
10135
3/4
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✓ Branch 3 taken 185 times.
426 for (auto &rid : *thd->m_main_security_ctx.get_active_roles()) {
10136
4/6
✓ Branch 0 taken 241 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
✓ Branch 5 taken 190 times.
241 if (rid == std::make_pair(lex_user, lex_host)) return 1;
10137 }
10138
10139 185 return 0;
10140 438 }
10141